perf: specialize comparison bitmap packing for 8-bit inputs - #9948
Conversation
Merging this PR will regress 4 benchmarks
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | WallTime | mul_u64_nonnull_neon |
28.9 µs | 40.4 µs | -28.63% |
| ❌ | Simulation | take_fsl_u32_random[256, 10] |
124.4 µs | 157.9 µs | -21.22% |
| ❌ | WallTime | mul_i64_nonnull_neon |
32.9 µs | 38.6 µs | -14.97% |
| ❌ | WallTime | multiply_shapes_neon[(32768, PerRowPerRow)] |
32.8 µs | 38.4 µs | -14.53% |
| ⚡ | WallTime | compare_u8_avx2 |
3.5 µs | 1.8 µs | +95.03% |
| ⚡ | WallTime | compare_u8_neon |
3.9 µs | 2.2 µs | +77.02% |
| ⚡ | WallTime | compare_u8_avx512 |
2.4 µs | 1.7 µs | +39.79% |
| ⚡ | Simulation | take_fsl_u32_random[16, 100] |
165.8 µs | 124.3 µs | +33.43% |
| ⚡ | Simulation | take_fsl_nullable_random[16, 100] |
187.7 µs | 162.9 µs | +15.25% |
| ⚡ | WallTime | dict_canonicalize_gt_u8_neon[1000000] |
547 µs | 488.3 µs | +12.03% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing mk/primitive-compare-bitmap (c215b0e) with develop (c3ade49)2
Footnotes
-
293 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
-
No successful run was found on
develop(ca2538d) during the generation of this report, so c3ade49 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩
Reuse collect_bool_word for primitive comparison bitmaps while preserving execution-context allocation and comparison semantics. Cover bitmap boundaries, all primitive types, nulls, and constant operand orientation. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Use byte packing only for i8/u8 and preserve the existing lane collectors for wider primitive types. The type selection folds away during monomorphization and avoids the wider AVX2 comparison regressions. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Keep type selection in collect_bits_dispatch and collect_zip_bits_dispatch, with independent narrow collectors and the existing wider collectors. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Limit the new boundary matrix to the i8/u8 specialization. Existing tests cover the unchanged wider primitive comparison paths. Signed-off-by: "Matt Katz" <mhkatz97@gmail.com> Signed-off-by: Matt Katz <mhkatz97@gmail.com>
6a69442 to
c215b0e
Compare
|
related: #9703 |
robert3005
left a comment
There was a problem hiding this comment.
Let's merge this, I know we will soon replace this with rowfn
Summary
Speed up comparisons over
i8andu8arrays by packing each 64-row group with the existingcollect_bool_wordhelper. The byte representation lets the compiler vectorize the comparison and bitmap construction efficiently.Dedicated
collect_bits_dispatchandcollect_zip_bits_dispatchhelpers select this path fromT::PTYPE, which is constant for each compiled primitive type. The byte-packing loops live separately incollect_bits_narrowandcollect_zip_bits_narrow. Wider integer and floating-point types continue to use the original lane collectors, so they avoid the AVX2 regressions from applying byte packing to wider masks.Changes
No benchmark source or public API changes. This primitive optimization is independent of NarrowArray.
Performance
Unchanged existing benchmarks on Apple M5 Max (aarch64), Rust 1.98.0, 8,192 rows.
compare_f32compare_floatcompare_intcompare_int_constantcompare_int_eqcompare_int_nullablecompare_u8compare_u64