Skip to content

Compare primitive values with RowFn - #9587

Draft
connortsui20 wants to merge 1 commit into
ct/row-fn-constant-decodefrom
ct/primitive-comparison-simd
Draft

Compare primitive values with RowFn#9587
connortsui20 wants to merge 1 commit into
ct/row-fn-constant-decodefrom
ct/primitive-comparison-simd

Conversation

@connortsui20

@connortsui20 connortsui20 commented Aug 24, 2026

Copy link
Copy Markdown
Member

Summary

Moves primitive comparisons entirely onto RowFn to measure the limits of the generic path. This removes the handwritten SIMD and primitive-specific fallback.

Changes

PrimitiveCompare declares INFALLIBLE = true and routes every primitive type, comparison operator, and constant orientation through multiversioned RowVisitor::visit_bool. Cross-generated optimized x86-64 IR and assembly show that LLVM vectorizes the row comparisons, but this does not establish end-to-end benchmark parity. CodSpeed results for this PR cover the accumulated stack, including #9680 direct constant decoding.

@connortsui20 connortsui20 added the changelog/performance A performance improvement label Aug 24, 2026
@codspeed-hq

codspeed-hq Bot commented Aug 24, 2026

Copy link
Copy Markdown

Merging this PR will regress 24 benchmarks

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 83 improved benchmarks
❌ 24 regressed benchmarks
✅ 2032 untouched benchmarks
🆕 18 new benchmarks
⏩ 106 skipped benchmarks1
🗄️ 4 archived benchmarks run2

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime lt_i64_nullable_avx512 2.9 µs 4.4 µs -35.26%
WallTime lt_i64_nullable_avx2 3 µs 4.4 µs -32.55%
WallTime lt_i64_nullable_neon 3.5 µs 4.9 µs -29.37%
WallTime compare_int_nullable_avx512 3.6 µs 5 µs -28.24%
WallTime mul_u64_nonnull_neon 15.2 µs 20.7 µs -26.72%
WallTime compare_int_nullable_avx2 3.9 µs 5.1 µs -22.21%
WallTime compare_int_nullable_neon 5 µs 6.2 µs -19.72%
WallTime eq_i64_constant_avx512 2.1 µs 2.6 µs -17.39%
Simulation int_gt[16] 97.3 µs 116.8 µs -16.68%
Simulation or_chain[16] 1.1 ms 1.4 ms -16.08%
Simulation int_gt[1024] 103.2 µs 121.8 µs -15.33%
Simulation or_chain[1024] 1.2 ms 1.4 ms -15.12%
WallTime mul_i64_nonnull_neon 17.1 µs 20 µs -14.6%
WallTime multiply_shapes_neon[(16384, PerRowPerRow)] 17.2 µs 20.1 µs -14.57%
Simulation float_gt[16] 237.3 µs 277.7 µs -14.54%
Simulation float_gt[1024] 262.3 µs 303.3 µs -13.53%
Simulation is_not_null_pred[1024] 203.7 µs 234.9 µs -13.27%
Simulation is_not_null_pred[16] 195 µs 224.4 µs -13.09%
Simulation cold_misaligned[(16, 64)] 345.6 µs 391.4 µs -11.7%
Simulation case_when_all_true[1000] 102.4 µs 115.4 µs -11.32%
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing ct/primitive-comparison-simd (139c28f) with develop (ba90f3d)3

Open in CodSpeed

Footnotes

  1. 106 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.

  2. 4 benchmarks were run, but are now archived. If they were deleted in another branch, consider rebasing to remove them from the report. Instead if they were added back, click here to restore them.

  3. No successful run was found on ct/row-fn-constant-decode (f21a243) during the generation of this report, so develop (ba90f3d) was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@connortsui20
connortsui20 force-pushed the ct/primitive-comparison-simd branch from 3e39406 to 931772a Compare August 24, 2026 21:34
@connortsui20
connortsui20 changed the base branch from develop to ct/compare-bench-cpu-features August 24, 2026 21:34
@connortsui20
connortsui20 force-pushed the ct/primitive-comparison-simd branch from 931772a to c0148bd Compare August 24, 2026 21:44
@connortsui20
connortsui20 changed the base branch from ct/compare-bench-cpu-features to ct/cpu-features-numeric-benches August 24, 2026 21:44
@connortsui20 connortsui20 changed the title Add SIMD primitive comparison kernels [DO NOT MERGE] Add SIMD primitive comparison kernels Aug 24, 2026
connortsui20 added a commit that referenced this pull request Aug 24, 2026
## Summary

The measurement half of #9587, split out so the numbers land before the
kernels do.

Bottom of a three-PR stack: this PR, then #9599, then #9587. Tagging
these with `#[cpu_features]` first means the walltime legs record the
portable lane kernel's throughput on `avx2`, `avx512`, and `neon` metal
as a baseline series. The kernel PR then reports against it rather than
introducing both the benchmark and the thing it measures in one diff.

## Changes

- Adds the primitive comparison cases a hand-written SIMD kernel would
have to beat: constant on the left, `u8`, `u64`, and `f32`.
- Tags those four with `#[cpu_features]`, so each walltime leg measures
them under its own build flags instead of in simulation. The existing
cases are untouched and keep their simulation series.
- `bench_compare` now carries an `ItemsCount`, so the report reads as
throughput rather than a time that only means something next to another
run over the same array length.
- Adds module docs recording why these four are tagged and the rest are
not.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/primitive-comparison-simd branch from c0148bd to 46ad4bb Compare August 24, 2026 23:30
Base automatically changed from ct/cpu-features-numeric-benches to develop August 25, 2026 01:35
connortsui20 added a commit that referenced this pull request Aug 25, 2026
…9599)

## Summary

Sweeps `#[cpu_features]` across the microbenchmarks that clearly earn
it: the binary numeric arithmetic and comparison kernels. Those are
portable lane loops — the source is identical on every target and the
vector width the compiler picks comes from the build flags — which is
the case the attribute exists for. Measuring them in simulation under
one fixed `+avx2` build hides the only variable that matters.

Middle of a three-PR stack: #9598, then this PR, then #9587. It carries
no kernel changes of its own — everything here is a benchmark attribute
— so it can be reordered or rebased onto `develop` without touching the
other two.

## Changes

Tagged:

- `binary_ops`: the primitive arithmetic cases (`add_*`, `subtract_*`,
`multiply_*`, `mul_*`, `div_i64_*`, `sub_i64_constant`, and the three
`*_shapes` matrices) and the two primitive comparison cases
(`eq_i64_constant`, `lt_i64_nullable`).
- `compare`: `compare_int`, `compare_int_nullable`,
`compare_int_constant`, `compare_int_eq`, `compare_float`.
- `scalar_subtract`.
- `lane_kernels`: `lanezip_checked_add_u32` and its
`arrow_checked_add_u32` baseline. The baseline is tagged too — comparing
the two is only meaningful under the same build flags.

Left in simulation, with the reasoning recorded in each file's module
docs:

- Decimal arithmetic and comparison: `i128` widening and per-lane
rescaling, not something a wider vector register decides.
- Boolean `and`/`or`: already word-at-a-time over a bitmap.
- String and struct comparison: dominated by view chasing and per-field
dispatch.
- Casts in `lane_kernels`: vectorization-sensitive, but out of scope
here.

Also left alone: the `between` benchmarks in `vortex-fastlanes`
(`new_raw_prim_test_between` is a raw-primitive comparison kernel and
does qualify) and the bit-packed comparison matrices. Both are `types
=`/`consts =` parameterized, which `#[cpu_features]` has no coverage for
yet, and both would fan out to dozens of walltime series. Worth a
follow-up rather than a guess in this PR.

Note that tagging moves a benchmark out of the sharded simulation job,
so these series restart on the walltime legs instead of continuing their
simulation history.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/primitive-comparison-simd branch 2 times, most recently from 1163162 to 4edd7e4 Compare August 27, 2026 19:42
@connortsui20 connortsui20 changed the title [DO NOT MERGE] Add SIMD primitive comparison kernels Compare primitive values with RowFn Aug 27, 2026
@connortsui20
connortsui20 changed the base branch from develop to ct/row-fn-bool-output-deferred August 27, 2026 19:43
@connortsui20
connortsui20 force-pushed the ct/primitive-comparison-simd branch 2 times, most recently from 72e2bc8 to ebda2b0 Compare August 27, 2026 21:22
@connortsui20
connortsui20 changed the base branch from ct/row-fn-bool-output-deferred to ct/row-fn-constant-decode August 27, 2026 21:23
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20
connortsui20 force-pushed the ct/primitive-comparison-simd branch from ebda2b0 to 139c28f Compare August 27, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/performance A performance improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant