feat[arrow-ord]: suppport REE comparisons#9621
Conversation
|
Unfortunately did not see there is an open PR #9448 before working on this, however I think this PR is more complete since #9448 does not seem to support REE with scalar or mixed comparisons. Also, this PR is more performant: |
79d81af to
eee179c
Compare
|
Super interesting. I suspect that the perf gain might go lower as # of phys indices grow as I'm avoiding copying them, but this definitely seems like a better implementation. |
arrow-ord/src/cmp.rs
Outdated
| fn apply<T: ArrayOrd>( | ||
| op: Op, | ||
| l: T, | ||
| l_s: bool, |
There was a problem hiding this comment.
Unless I'm mistaken, you can have only one of l_s == true / l_v.is_some() / l_ree.is_some() at a time. How about introducing an enum? It will reduce the arg # and make them clearer
There was a problem hiding this comment.
I don't think that's right. Scalars can have ree and/or dictionary types and l_v and l_ree are both Some for Ree
There was a problem hiding this comment.
Ah, right! Still, I think that the too_many_arguments link is legit, and I'd consider groupin the args for each side -- either anonymous 3-tuple or a real struct. It would make the call site much cleaner. e.g.
struct ArrayInfo<'a> {
is_scalar: bool,
dict_values: &'a dyn AnyDictionyArray,
run_array: Option<&'a ReeInfo>,
}
85034d0 to
791ec8c
Compare
|
Thanks for the review @brunal. I addressed all your comments. |
arrow-ord/src/cmp.rs
Outdated
| fn apply<T: ArrayOrd>( | ||
| op: Op, | ||
| l: T, | ||
| l_s: bool, |
There was a problem hiding this comment.
Ah, right! Still, I think that the too_many_arguments link is legit, and I'd consider groupin the args for each side -- either anonymous 3-tuple or a real struct. It would make the call site much cleaner. e.g.
struct ArrayInfo<'a> {
is_scalar: bool,
dict_values: &'a dyn AnyDictionyArray,
run_array: Option<&'a ReeInfo>,
}
| } | ||
| } | ||
|
|
||
| fn ree_physical_indices(info: &ReeInfo) -> Vec<usize> { |
There was a problem hiding this comment.
you can turn this into a .skip().map_while(...) to return an Iterator<Item = usize>. Then in logical_indices's Some-Some branch, you can directly map on it. This avoid materializing the intermediate physical indices vector.
This is very nitpicky, as the one branch that benefits from this, REE<dict>, seems like quite a niche use case :)
There was a problem hiding this comment.
I think I'm going to keep this as is currently written to mirror the dict normalized_keys materialization. We can do this as a follow up improvement if we see it's worth it.
791ec8c to
a3669d9
Compare
|
Updated, apologies for the delay. |
brunal
left a comment
There was a problem hiding this comment.
Looks excellent to me, now you just need someone with repo rights :-)
This commit implements native comparisons on REE-encoded arrays which are treated similarly to dictionary indirection. This commit implements REE to scalar comparisons by operating on the physical values only then bulk expanding the boolean result. REE-to-REE comparisons are also optimized by computing aligned physical value runs to minimize comparisons. Mixed cases (REE vs flat) materialize a logical index mapping similar to dictionaries. This commit also supports REE<Dict>. For comparison, here are the benchmark results with flat arrays as a reference on my local machine: ``` eq Int32 time: [14.955 µs 15.162 µs 15.396 µs] eq scalar Int32 time: [11.379 µs 11.418 µs 11.459 µs] ree_comparison/eq_ree_scalar(phys=64,log=65536) time: [453.31 ns 454.88 ns 456.43 ns] ree_comparison/eq_ree_scalar(phys=1024,log=65536) time: [4.1224 µs 4.1298 µs 4.1368 µs] ree_comparison/eq_ree_scalar(phys=32768,log=65536) time: [93.506 µs 94.085 µs 94.993 µs] ree_comparison/eq_ree_ree(phys=64,log=65536) time: [413.96 ns 414.82 ns 415.87 ns] ree_comparison/eq_ree_ree(phys=1024,log=65536) time: [4.1597 µs 4.1660 µs 4.1749 µs] ree_comparison/eq_ree_ree(phys=32768,log=65536) time: [128.74 µs 144.40 µs 161.53 µs] ``` As is expected, the more we take advantage of REE encoding, the faster the comparisons are. Signed-off-by: Alfonso Subiotto Marques <alfonso.subiotto@polarsignals.com>
a3669d9 to
08e2e39
Compare
|
Friendly ping for a review or triage @alamb (not sure if there's another code owner) |
|
Thanks for the ping @asubiotto -- I'll try and find time to review this, but I am having a hard time finding time |
|
But nwo I see @brunal has already done it so that will make it easier |
|
Thanks! Appreciate the time. Yes, @brunal conducted an in-depth review so I only need a final look from a maintainer. |
This commit implements native comparisons on REE-encoded arrays which are treated similarly to dictionary indirection.
This commit implements REE to scalar comparisons by operating on the physical values only then bulk expanding the boolean result.
REE-to-REE comparisons are also optimized by computing aligned physical value runs to minimize comparisons.
Mixed cases (REE vs flat) materialize a logical index mapping similar to dictionaries.
This commit also supports
REE<Dict>.For comparison, here are the benchmark results with flat arrays as a reference on my local machine:
As is expected, the more we take advantage of REE encoding, the faster the comparisons are.
Which issue does this PR close?
RunArray(Run Length Encoding (RLE) / Run End Encoding (REE) support) #3520Rationale for this change
Feature enhancement for comparisons
What changes are included in this PR?
Support for REE comparisons, including tests and benchmarks.
Are these changes tested?
Yes.
Are there any user-facing changes?
REE comparisons are now supported.