Repository navigation
Blocked BitPacked: fuse FoR decode over blocked children - #10251
Conversation
Merging this PR will improve performance by 11.2%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | bitpack_blocked_decompress_neon[u32] |
14.3 µs | 12.7 µs | +12.38% |
| ⚡ | WallTime | bitpack_blocked_decompress_avx512[u32] |
9.4 µs | 8.6 µs | +10.04% |
| 🆕 | WallTime | decode_blocked_bitpacked_chunked_avx2[i64, 524288] |
N/A | 20.8 µ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 µs | N/A |
| 🆕 | WallTime | decode_blocked_bitpacked_chunked_avx512[u32, 524288] |
N/A | 17.5 µs | N/A |
| 🆕 | WallTime | decode_blocked_bitpacked_chunked_neon[i64, 524288] |
N/A | 27.7 µs | N/A |
| 🆕 | WallTime | decode_blocked_bitpacked_chunked_neon[u32, 524288] |
N/A | 26.7 µs | N/A |
Tip
Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.
Comparing mk/for-bitpacked-blocked-fused (8f30906) with develop (d42e7c9)
8da23f9 to
3711acb
Compare
Signed-off-by: Matt Katz <[email protected]>
Signed-off-by: Matt Katz <[email protected]>
Signed-off-by: Matt Katz <[email protected]>
0b18f5c to
8f30906
Compare
| // `range` counts from the start of the first chunk, and the output starts at `offset`. | ||
| let skip = offset.saturating_sub(range.start); | ||
| let dst = &mut output[range.start + skip - offset..range.end - offset]; | ||
| if dst.len() == FL_CHUNK_SIZE { |
There was a problem hiding this comment.
If I understand correctly, the issue may be that dst.len() may be less than chunk size. If it's greater, we currently copy to a scratch buffer although we can copy it to dst as there's sufficient capacity.
When exactly can dst.len() be less than a chunk size? When we are exporting the tail?
This is not exactly related to your change, but the exiting code seems suspicious to me
There was a problem hiding this comment.
There are three cases when dst.len() < FL_CHUNK_SIZE:
offset > 0, which happens for an array that has been sliced. sohead.len() < FL_CHUNK_SIZEtail.len() < FL_CHUNK_SIZE- both of the above
e.g.:
offset = 100, len = 2500
chunk 0 chunk 1 chunk 2
position 0 1024 2048 2600 3072
┌───────────────────────┬──────────────────────┬────────────────────────┐
packed │ offset ┆ 924 │ 1024 │ 552 ┆ unused │
└───────────────────────┴──────────────────────┴────────────────────────┘
▼ ▼ ▼ ▼
output 0 924 1948 2500
├──────────────┼──────────────────────┼─────────────┤
dst: 924 dst: 1024 dst: 552
via scratch unpack in place via scratch
There was a problem hiding this comment.
It will never be greater
Tracking Issue: #10167
Summary
FoRnow decodes a blockedBitPackedchild in one pass, the same as a global-width child. Before, the child was decoded to a primitive array first and the references were added in a second pass.A block and a FoR chunk are both 1024 values, so each block unpacks at its own width and adds its chunk's reference directly.
Changes
unpack_chunkswalks the blocks of a blocked child, each at its own width.execute_block_offsetsandfor_each_packed_blockare shared with the blockedBitPackeddecoder.u64directly instead of through a lazycast.Benchmarks
for_decode, per-chunk references, local M5 Max:Testing
fused_decode_is_wrapping_adddraws a bit width per block.for_fuses_blocked_childcovers partial blocks, zero and native widths, and constant and per-chunk references.Follow-up
FoRSchemestill bit-packs its child withBITPACKING_V1, so the compressor doesn't write this combination yet. That needs #10245.