Skip to content

feat: specialize primitive sums for constant and run-end arrays - #9821

Closed
connortsui20 wants to merge 1 commit into
developfrom
ct/constant-runend-sum
Closed

feat: specialize primitive sums for constant and run-end arrays#9821
connortsui20 wants to merge 1 commit into
developfrom
ct/constant-runend-sum

Conversation

@connortsui20

@connortsui20 connortsui20 commented Sep 9, 2026

Copy link
Copy Markdown
Member

Split into two independent draft PRs: constant sums #9822 and run-end sums #9823.

Summary

Computes primitive Sum and SumV2 over constant and run-end arrays without expanding repeated values, including grouped aggregation. Decimal inputs keep their existing paths. Weighted floating-point sums can round differently from repeated addition, as existing constant sums do.

Changes

Run-end sums weight values by their run lengths, use fused multiply-add to preserve finite cancellation, and share a run cursor across fixed-size groups. Constant groups reuse scalar multiplication, and both encodings use helpers for SumV2 partial states.

Tests and validation

New tests compare the kernels with decoded primitive arrays and cover nulls, slices, empty groups, overflow, NaNs, finite cancellation, and decimal fallback.

  • cargo nextest run -p vortex-array -p vortex-runend --lib: 3,679 passed, 1 skipped.
  • cargo test --doc -p vortex-array -p vortex-runend: passed.
  • cargo clippy --all-targets --all-features -- -D warnings: passed.
  • cargo +nightly fmt -p vortex-array -p vortex-runend -- --check and taplo fmt --check: passed.
  • Full workspace Rust formatting reports four existing macro-format differences in vortex-duckdb and vortex-ffi, outside this diff.
Benchmark results

Local medians on aarch64-apple-darwin with Rust 1.98.0, using cargo bench -p vortex-runend --bench run_end_sum -- --sample-count 100. Both modes use revision ae99ee84fe65813994cd432a495a99ae7e84b705, with the baseline disabling the new encoding kernels in its session.

Each input has 16,384 i32 elements. The run-end cases use nullable values and 64-element runs. Grouped timings include finalization to a primitive array.

Workload Specialized Kernels disabled
Run-end, whole array 1.551 µs 5.624 µs
Run-end, 2-element groups 38.29 µs 81.45 µs
Run-end, 128-element groups 2.728 µs 6.499 µs
Constant, 128-element groups 6.541 µs 88.2 µs

The benchmark also covers run lengths 4 and 1,024 and group sizes 1 and 8.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20 connortsui20 added the changelog/performance A performance improvement label Sep 9, 2026
@codspeed-hq

codspeed-hq Bot commented Sep 9, 2026

Copy link
Copy Markdown

Merging this PR will regress 2 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

⚡ 3 improved benchmarks
❌ 2 regressed benchmarks
✅ 2188 untouched benchmarks
🆕 38 new benchmarks
⏩ 218 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation random_i16[0.8] 75.5 µs 93.9 µs -19.65%
WallTime mul_u32_nonnull_avx512 5.5 µs 6.3 µs -11.32%
Simulation random_i8[0.5] 91.4 µs 68.1 µs +34.17%
WallTime dict_canonicalize_gt_u8_neon[1000000] 567.1 µs 486.8 µs +16.5%
WallTime dict_canonicalize_gt_u8_neon[16000000] 9.3 ms 8 ms +15.7%
🆕 Simulation grouped_constant_fallback[1] N/A 161.6 ms N/A
🆕 Simulation grouped_constant_fallback[128] N/A 1.4 ms N/A
🆕 Simulation grouped_constant_fallback[2] N/A 81 ms N/A
🆕 Simulation grouped_constant_fallback[8] N/A 20.3 ms N/A
🆕 Simulation grouped_constant[1] N/A 13 ms N/A
🆕 Simulation grouped_constant[128] N/A 211.8 µs N/A
🆕 Simulation grouped_constant[2] N/A 6.5 ms N/A
🆕 Simulation grouped_constant[8] N/A 1.7 ms N/A
🆕 Simulation grouped_runend_fallback[1, 1024] N/A 5.2 ms N/A
🆕 Simulation grouped_runend_fallback[1, 4] N/A 5.8 ms N/A
🆕 Simulation grouped_runend_fallback[1, 64] N/A 5.2 ms N/A
🆕 Simulation grouped_runend_fallback[128, 1024] N/A 282.5 µs N/A
🆕 Simulation grouped_runend_fallback[128, 4] N/A 853.8 µs N/A
🆕 Simulation grouped_runend_fallback[128, 64] N/A 288.8 µs N/A
🆕 Simulation grouped_runend_fallback[2, 1024] N/A 2.7 ms N/A
... ... ... ... ... ...

ℹ️ 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/constant-runend-sum (ae99ee8) with develop (e3b8eb2)

Open in CodSpeed

Footnotes

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

@connortsui20
connortsui20 deleted the ct/constant-runend-sum branch September 9, 2026 18:40
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