Skip to content

Blocked BitPacked: fuse FoR decode over blocked children - #10251

Draft
mhk197 wants to merge 27 commits into
mk/bitpacked-v2-schemefrom
mk/for-bitpacked-blocked-fused
Draft

mhk197 wants to merge 27 commits into
mk/bitpacked-v2-schemefrom
mk/for-bitpacked-blocked-fused

Conversation

@mhk197

@mhk197 mhk197 commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Tracking Issue: #10167

Stacked on #10245; this PR targets mk/bitpacked-v2-scheme.

Summary

FoR decodes a blocked BitPacked child through the fused unpack, with a single reference or with per-chunk references. Before, FoR::execute required a global bit width for the fused path, so a blocked child was decoded to a primitive array first and the references were added in a second pass.

Design

  • unpack_chunks in for_decompress.rs matches on bit_widths(). A global width walks the chunks with for_each_packed_chunk as before. Blocked widths walk the blocks with a new crate-private for_each_packed_block, and both feed the same unpack-and-add closure, so each block unpacks at its own width with unchecked_unfor_pack.
  • The block offsets are executed and validated by execute_block_offsets, which is extracted from unpack_into_primitive_builder_blocked so that both decoders check the boundaries the same way before unpacking without bounds checks.
  • FoR::execute drops the is_global() condition from its fused predicate. The chunk alignment condition is unchanged: blocks line up with FoR chunks when the reference is constant or the offsets match.
  • execute_block_offsets widens the executed offsets to u64 directly instead of executing a lazy cast. The block loop still compiles once per value type. This removes a fixed cost of about 0.25 µs per array, which also speeds up blocked BitPacked decoding on its own.

Benchmarks

Local walltime on an M5 Max, median of 7–9 interleaved runs against the parent commit. The machine was under load, so differences up to about 5% are noise.

for_decode (in this PR): FoR with per-chunk references over 512 KiB of values. The blocked child packs every block at the global child's width, so the packed bytes are the same.

Benchmark Before After
decode_bitpacked_chunked/u32 (global width) 9.62 µs 9.62 µs
decode_blocked_bitpacked_chunked/u32 18.54 µs 9.87 µs (0.53x)
decode_bitpacked_chunked/i64 (global width) 11.95 µs 11.91 µs
decode_blocked_bitpacked_chunked/i64 20.04 µs 12.29 µs (0.61x)

bitpack_blocked_decompress (from #10202, blocked BitPacked without FoR): u32 5.17 → 4.92 µs, u64 12.12 → 11.49 µs, from the offset widening.

A local matrix (not committed) decoded FoR over BitPacked for every combination of global or per-chunk references and global or per-block widths, for u32 and i64. With 64 blocks of u32, blocked widths now decode in 0.50–0.58x of the time they took before:

u32, 64 blocks Global width Blocked widths, before Blocked widths, after
uniform (7 bits everywhere), per-chunk references 4.87 µs 9.00 µs 4.92 µs
varying (1 to 16 bits by block), per-chunk references 4.92 µs 9.41 µs 4.75 µs
drift (7 bits above a base that grows by block), per-chunk references 4.87 µs 9.33 µs 4.96 µs

Small arrays isolate the fixed cost per array. For one block of u32 with per-chunk references, a blocked child took 0.79 µs before, 0.50 µs with the fused path alone, and 0.25 µs once the offsets skip the cast. A global-width child takes 0.24 µs.

Testing

  • for_::tests::fused_decode_is_wrapping_add (hegel) also draws a width per block, from zero to the native width, so blocked children cover every integer type with patches, nulls, a constant or per-chunk references, and slices.
  • blocked::tests::for_fuses_blocked_child builds blocked children that start within their first block, hold zero and native width blocks and have FoR-encoded offsets, under constant and per-chunk references.
  • Breaking the blocked arm of unpack_chunks fails both tests and the existing for_decodes_blocked_child.
  • cargo nextest run -p vortex-fastlanes -p vortex-btrblocks: 755 passed.
  • cargo clippy -p vortex-fastlanes --all-targets --all-features -- -D warnings passes.
  • cargo +nightly-2026-09-10 fmt -p vortex-fastlanes --check reports only benches/bitpack_blocked_decompress.rs, which comes from the base branch and is already formatted further down the stack.
  • Not run: doctests, CUDA.

Follow-ups

  • Bit-pack FoR's encoded child per block. FoRScheme still bit-packs its child with BITPACKING_V1, so the compressor never writes FoR over blocked BitPacked yet. This PR makes that combination decode as fast as a global width.

mhk197 added 27 commits October 2, 2026 15:05
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
…ked.v2 is allowed

Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
@mhk197 mhk197 added the changelog/performance A performance improvement label Oct 2, 2026
@codspeed

codspeed Bot commented Oct 2, 2026

Copy link
Copy Markdown

Merging this PR will regress 1 benchmark

⚠️ 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.

⚡ 4 improved benchmarks
❌ 1 regressed benchmark
✅ 2107 untouched benchmarks
🆕 6 new benchmarks
⏩ 503 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ WallTime bitpack_blocked_compress_avx2 6.8 µs 7.7 µs -11.74%
⚡ WallTime bitpack_blocked_decompress_avx512[u32] 9.9 µs 8.7 µs +14.44%
⚡ WallTime bitpack_blocked_decompress_avx2[u32] 11.2 µs 10.1 µs +11.83%
⚡ WallTime bitpack_blocked_decompress_avx512[u64] 20.1 µs 18 µs +11.56%
⚡ WallTime bitpack_blocked_decompress_neon[u32] 14.1 µs 12.7 µs +10.72%
🆕 WallTime decode_blocked_bitpacked_chunked_avx2[i64, 524288] N/A 20.9 µs N/A
🆕 WallTime decode_blocked_bitpacked_chunked_avx2[u32, 524288] N/A 20.6 µs N/A
🆕 WallTime decode_blocked_bitpacked_chunked_avx512[i64, 524288] N/A 18.3 µs N/A
🆕 WallTime decode_blocked_bitpacked_chunked_avx512[u32, 524288] N/A 17.8 µs N/A
🆕 WallTime decode_blocked_bitpacked_chunked_neon[i64, 524288] N/A 28.1 µs N/A
🆕 WallTime decode_blocked_bitpacked_chunked_neon[u32, 524288] N/A 27.1 µs N/A

Tip

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


Comparing mk/for-bitpacked-blocked-fused (0b18f5c) with mk/bitpacked-v2-scheme (c98cb99)

Open in CodSpeed

Footnotes

  1. 503 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. ↩

@mhk197
mhk197 force-pushed the mk/bitpacked-v2-scheme branch from c98cb99 to f638117 Compare October 9, 2026 14:53

This branch has not been deployed

No deployments
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