Repository navigation
perf: speed up DictionaryArray hashing - #26159
Rich-T-kid wants to merge 5 commits into
Conversation
d00c2a0 to
63799c2
Compare
|
run benchmark with_hashes |
|
Benchmark for this request failed before finishing (Kubernetes reason: Benchmarks requested: Runner log (last 40 lines)Kubernetes messageFile an issue against this benchmark runner |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #26159 +/- ##
==========================================
+ Coverage 81.38% 82.76% +1.38%
==========================================
Files 1116 1148 +32
Lines 397960 451186 +53226
Branches 397960 451186 +53226
==========================================
+ Hits 323880 373435 +49555
+ Misses 55120 55008 -112
- Partials 18960 22743 +3783 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
show benchmark queue |
|
Hi @Rich-T-kid, you asked to view the benchmark queue (#26159 (comment)). No pending jobs. File an issue against this benchmark runner |
|
run benchmark with_hashes |
|
Benchmark for this request failed before finishing (Kubernetes reason: Benchmarks requested: Runner log (last 40 lines)Kubernetes messageFile an issue against this benchmark runner |
|
run benchmark with_hashes |
|
run benchmark with_hashes |
|
🤖 Benchmark running (GKE) | trigger CPU Details (lscpu)Comparing rich-T-kid/faster-dict-hash (05bcf90) to 1c49b7f (merge-base) diff Run configurationrun benchmark with_hashesResults will be posted here when complete File an issue against this benchmark runner |
|
🤖 Benchmark running (GKE) | trigger CPU Details (lscpu)Comparing rich-T-kid/faster-dict-hash (05bcf90) to 1c49b7f (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"Results will be posted here when complete File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Instance: Comparing rich-T-kid/faster-dict-hash (05bcf90) to 1c49b7f (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"CPU Details (lscpu)Details
Resource Usagewith_hashes — base (merge-base)
with_hashes — branch
File an issue against this benchmark runner |
|
run benchmark with_hashes |
05bcf90 to
2b50497
Compare
|
cc @mightsleep @alamb if your in the mood to review more bit manipulation code 😄. I think this is less intense than whats going on in arrow-rs 😆 |
|
🤖 Benchmark running (GKE) | trigger CPU Details (lscpu)Comparing rich-T-kid/faster-dict-hash (05bcf90) to 1c49b7f (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"Results will be posted here when complete File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Instance: Comparing rich-T-kid/faster-dict-hash (05bcf90) to 1c49b7f (merge-base) diff Run configurationrun benchmark with_hashesCPU Details (lscpu)Details
Resource Usagewith_hashes — base (merge-base)
with_hashes — branch
File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Instance: Comparing rich-T-kid/faster-dict-hash (05bcf90) to 1c49b7f (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"CPU Details (lscpu)Details
Resource Usagewith_hashes — base (merge-base)
with_hashes — branch
File an issue against this benchmark runner |
alamb
left a comment
There was a problem hiding this comment.
Thanks @Rich-T-kid -- this is still pretty intense LOL. I left some thoughts let me know whatyou think
Rework hash_dictionary_scatter so the key-null handling runs in 64-bit BitChunks instead of per-row Option unwrap, and route all-valid chunks plus the no-null-keys fast path through an 8-way unrolled dense scatter that keeps the dict gather pipeline full. Mixed chunks use a branchless csel blend (safe-clamped indices) when dict values are all valid; the rarer HAS_NULL_VALUES mixed path falls back to the per-bit scan for correctness. Benchmarks (datafusion/common/benches/with_hashes.rs, Apple M4 Max): dictionary_utf8_int32 single, no nulls : 2.91 µs -> 1.83 µs (-37%) dictionary_utf8_int32 multiple, no nulls: 9.10 µs -> 5.67 µs (-38%) dictionary_utf8_int32 single, nulls : 7.11 µs -> 2.81 µs (-60%) dictionary_utf8_int32 multiple, nulls : 20.90 µs -> 8.21 µs (-61%) Non-dict benchmarks (int64, utf8_view small) stay within noise.
6117012 to
88d50e0
Compare
|
run benchmark with_hashes |
1 similar comment
|
run benchmark with_hashes |
|
yes hello, |
|
🤖 Benchmark running (GKE) | trigger CPU Details (lscpu)Comparing rich-T-kid/faster-dict-hash (88d50e0) to d137137 (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"Results will be posted here when complete File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Instance: Comparing rich-T-kid/faster-dict-hash (88d50e0) to d137137 (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"CPU Details (lscpu)Details
Resource Usagewith_hashes — base (merge-base)
with_hashes — branch
File an issue against this benchmark runner |
|
🤖 Benchmark running (GKE) | trigger CPU Details (lscpu)Comparing rich-T-kid/faster-dict-hash (88d50e0) to d137137 (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"Results will be posted here when complete File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Instance: Comparing rich-T-kid/faster-dict-hash (88d50e0) to d137137 (merge-base) diff Run configurationrun benchmark with_hashes
env:
BENCH_FILTER: "dict"CPU Details (lscpu)Details
Resource Usagewith_hashes — base (merge-base)
with_hashes — branch
File an issue against this benchmark runner |
|
Bot numbers match mine, nulls went from 2.1-2.4x to 1.13-1.16x without the mask walk. |
|
hmm I think its okay to break up the changes then. I think a 15-43% is good for a single PR and then I can build on top of it afterwards. I think @alamb is also in favor of this style |
| } else { | ||
| *hash = dict_hashes[idx]; | ||
| } | ||
| let dict_hash = unsafe { *dict_hashes.get_unchecked(idx) }; |
There was a problem hiding this comment.
should add a saftey comment
Which issue does this PR close?
Rationale for this change
see issue, the cost for hashing dictionary arrays comes down to a writing corresponding values to their key indices, we can speed this up with branchless code.
What changes are included in this PR?
Rewrites the scatter as four const-generic specializations:
valid values,
trailing_zerosbit-walk otherwise)What is the testing strategy for this PR?
existing test cover this path
Are there any user-facing changes?
no