Skip to content

GH-34569: [C++] Diffing of Run-End Encoded arrays - #35003

Merged
bkietz merged 16 commits into
apache:mainfrom
felipecrv:diff_ree
Oct 26, 2023
Merged

bkietz merged 16 commits into
apache:mainfrom
felipecrv:diff_ree

Conversation

@felipecrv

@felipecrv felipecrv commented Apr 10, 2023 •

Copy link
Copy Markdown
Contributor

What changes are included in this PR?

Ability to diff run-end encoded arrays without expanding them first. This is useful for debugging and understanding of unit test failures.

Many successive random accesses to REE arrays by logical indices incur many successive binary searches on the run-ends array to find the physical index of the values array, so this PR implements a few interesting optimizations -- the most complicated one is encapsulated in a new utility available via ree_util.h as there are many potential uses for it other than diffing.

+-------------+---------------------------+----------------------------------------------------+
|             |                                  Optimizations                                 |
+-------------+---------------------------+-----------------------+----------------------------+
| # bsearches | Null checks on Comparator | RunLengthOfEqualsFrom | Cached FindPhysicalIndex() |
+-------------+---------------------------+----------------------+-----------------------------+
|    3798     |                           |                      |                             |
+-------------+---------------------------+----------------------+-----------------------------+
|    1914     |           X               |                      |                             |
+-------------+---------------------------+----------------------+-----------------------------+
|     180     |           X               |        X             |                             |
+-------------+---------------------------+----------------------+-----------------------------+
|     153     |           X               |                      |           X                 |
+-------------+---------------------------+----------------------+-----------------------------+
|      75     |           X               |        X             |           X                 |
+-------------+---------------------------+----------------------+-----------------------------+

Are these changes tested?

Yes. By existing and newly added REE-specific tests.

Are there any user-facing changes?

No.

@github-actions

Copy link
Copy Markdown

…mparator

This will allow different comparator to initialize and keep *mutable
state* between the calls to Equals. This can also be done with mutable
lambdas, but I believe this way is much readable and safer even though
it's a bit verbose.
@felipecrv
felipecrv marked this pull request as ready for review October 24, 2023 03:06
@felipecrv
felipecrv requested review from bkietz and mapleFU October 24, 2023 03:06
This approximately halves the number of binary searches performed during
diffing to resolve physical index on REE arrays.

The number goes from 3798 to 1914 (~= 1899 = 3798/2).
…EE arrays

This makes the number of binary searches to find physical indices go
from 1914 to 180 during the execution of diff tests on REEs.

I took care of not including the newly added test in this accounting.
When new queries for the physical index of a logical index come in,
binary search is performed again but the first candidate checked is the
result of the previous search (cached physical index) instead of the
midpoint of the run-ends array.

If that test fails, FindPhysicalIndex() is called with one of the
partitions defined by the cached index. If the queried logical indices
follow an increasing or decreasing pattern, this first test is much more
effective in (1) finding the answer right away (close logical indices belong
to the same runs) or (2) discarding many more candidates than probing
the midpoint would.

The most adversarial case -- alternating between 0 and length-1 queries --
only adds one extra binary search probe when compared to always starting
binary search from the midpoint without any of these optimizations.

This optimization further reduces the number of binary searches
performed during arrow-diff-test from 180 to 75. Which is a
log2(n) speed-up (180/log2(180) ~= 79.81).

Without the RunLengthOfEqualsFrom optimization, this optimization alone
reduces the number of binary searches from 1914 to 153.

+-------------+---------------------------+----------------------------------------------------+
|             |                                  Optimizations                                 |
+-------------+---------------------------+-----------------------+----------------------------+
| # bsearches | Null checks on Comparator | RunLengthOfEqualsFrom | Cached FindPhysicalIndex() |
+-------------+---------------------------+----------------------+-----------------------------+
|    3798     |                           |                      |                             |
+-------------+---------------------------+----------------------+-----------------------------+
|    1914     |           X               |                      |                             |
+-------------+---------------------------+----------------------+-----------------------------+
|     180     |           X               |        X             |                             |
+-------------+---------------------------+----------------------+-----------------------------+
|     153     |           X               |                      |           X                 |
+-------------+---------------------------+----------------------+-----------------------------+
|      75     |           X               |        X             |           X                 |
+-------------+---------------------------+----------------------+-----------------------------+

@bkietz bkietz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach looks good to me, just a few style nits

Comment thread cpp/src/arrow/util/ree_util.cc Resolved
Comment thread cpp/src/arrow/util/ree_util.cc Resolved
Comment thread cpp/src/arrow/util/ree_util.cc Resolved
Comment thread cpp/src/arrow/array/diff.cc Resolved
Comment thread cpp/src/arrow/array/diff.cc Resolved
Comment thread cpp/src/arrow/array/diff.cc Resolved
Comment thread cpp/src/arrow/array/diff.cc Resolved
Comment thread cpp/src/arrow/array/diff.cc Resolved

@bkietz bkietz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bkietz
bkietz merged commit fcbcb7d into apache:main Oct 26, 2023
@felipecrv
felipecrv deleted the diff_ree branch October 26, 2023 21:42
@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 5 benchmarking runs that have been run so far on merge-commit fcbcb7d.

There was 1 benchmark result indicating a performance regression:

The full Conbench report has more details.

loicalleyne pushed a commit to loicalleyne/arrow that referenced this pull request Nov 13, 2023
### What changes are included in this PR?

Ability to diff run-end encoded arrays without expanding them first. This is useful for debugging and understanding of unit test failures.

Many successive random accesses to REE arrays by logical indices incur many successive binary searches on the run-ends array to find the physical index of the values array, so this PR implements a few interesting optimizations -- the most complicated one is encapsulated in a new utility available via `ree_util.h` as there are many potential uses for it other than diffing.

    +-------------+---------------------------+----------------------------------------------------+
    |             |                                  Optimizations                                 |
    +-------------+---------------------------+-----------------------+----------------------------+
    | # bsearches | Null checks on Comparator | RunLengthOfEqualsFrom | Cached FindPhysicalIndex() |
    +-------------+---------------------------+----------------------+-----------------------------+
    |    3798     |                           |                      |                             |
    +-------------+---------------------------+----------------------+-----------------------------+
    |    1914     |           X               |                      |                             |
    +-------------+---------------------------+----------------------+-----------------------------+
    |     180     |           X               |        X             |                             |
    +-------------+---------------------------+----------------------+-----------------------------+
    |     153     |           X               |                      |           X                 |
    +-------------+---------------------------+----------------------+-----------------------------+
    |      75     |           X               |        X             |           X                 |
    +-------------+---------------------------+----------------------+-----------------------------+
    
### Are these changes tested?

Yes. By existing and newly added REE-specific tests.

### Are there any user-facing changes?

No.

* Closes: apache#34569

Authored-by: Felipe Oliveira Carvalho <[email protected]>
Signed-off-by: Benjamin Kietzman <[email protected]>
dgreiss pushed a commit to dgreiss/arrow that referenced this pull request Feb 19, 2024
### What changes are included in this PR?

Ability to diff run-end encoded arrays without expanding them first. This is useful for debugging and understanding of unit test failures.

Many successive random accesses to REE arrays by logical indices incur many successive binary searches on the run-ends array to find the physical index of the values array, so this PR implements a few interesting optimizations -- the most complicated one is encapsulated in a new utility available via `ree_util.h` as there are many potential uses for it other than diffing.

    +-------------+---------------------------+----------------------------------------------------+
    |             |                                  Optimizations                                 |
    +-------------+---------------------------+-----------------------+----------------------------+
    | # bsearches | Null checks on Comparator | RunLengthOfEqualsFrom | Cached FindPhysicalIndex() |
    +-------------+---------------------------+----------------------+-----------------------------+
    |    3798     |                           |                      |                             |
    +-------------+---------------------------+----------------------+-----------------------------+
    |    1914     |           X               |                      |                             |
    +-------------+---------------------------+----------------------+-----------------------------+
    |     180     |           X               |        X             |                             |
    +-------------+---------------------------+----------------------+-----------------------------+
    |     153     |           X               |                      |           X                 |
    +-------------+---------------------------+----------------------+-----------------------------+
    |      75     |           X               |        X             |           X                 |
    +-------------+---------------------------+----------------------+-----------------------------+
    
### Are these changes tested?

Yes. By existing and newly added REE-specific tests.

### Are there any user-facing changes?

No.

* Closes: apache#34569

Authored-by: Felipe Oliveira Carvalho <[email protected]>
Signed-off-by: Benjamin Kietzman <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C++] Diffing of Run-End Encoded arrays

2 participants