bench: run the full compress suite under --gpu-decompress - #9399
bench: run the full compress suite under --gpu-decompress#9399joseph-isaacs wants to merge 11 commits into
--gpu-decompress#9399Conversation
Drop the incremental GPU allow-list so --gpu-decompress runs every dataset in the compress suite, and include the airquality dataset on the GPU path. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
airquality and rplace come from the same pcodec bucket, so gate them consistently: the GPU suite runs every compress dataset. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merging this PR will degrade performance by 1.6%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | WallTime | words_gather_scalar[65536] |
8.3 µs | 9.4 µs | -11.98% |
| ⚡ | WallTime | words_gather_dispatch[1024] |
33 ns | 30 ns | +10% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing claude/gpu-compress-benchmarks-x788xc (8d6595e) with develop (1a493b6)
Footnotes
-
46 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. ↩
GPU Compression |
The CUDA DateTimeParts executor dispatched with match_each_signed_integer_ptype, so it panicked with "Unsupported ptype u16" on the taxi benchmark. Compression picks the narrowest ptype per component, and the CPU decoder already accepts any integer ptype, so match the CPU behaviour and generate the kernel for every signed and unsigned integer width. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
RunEnd GPU decoding bailed when values carried Validity::Array. The error message claimed a CPU fallback, but execute_cuda can only fall back while all buffers are host-resident, so a device-resident scan (as in the GPU compression benchmark) failed outright. Add a runend_bool kernel that expands the per-run validity bitmap through the same run mapping as the values. Each thread owns a whole output byte so threads never race on bits within a byte. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Public BI datasets are converted from CSV with the DuckDB CLI, which the CPU benchmark runner already installs. The GPU job never needed it while its suite was a single TPC-H dataset; now that it runs the full suite, Arade fails with "No such file or directory" when spawning duckdb. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The GPU compression benchmark failed on Euro2016 with "No CUDA kernel for encoding vortex.masked". A MaskedArray is a child array that carries no nulls of its own plus the validity bitmap that supplies them, so decode the child on the GPU, decode the mask on the GPU, and attach the mask to the result. Bail when the child itself carries a per-element validity bitmap: intersecting two device-resident bitmaps would need a CPU compute pass, and MaskedArray's own invariant makes that case unreachable for well-formed arrays. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Canonical arrays keep validity as a separate child array, and into_host moved
only the data buffer, leaving a device-resident bitmap that CPU compute cannot
read ("unwrap_host called for Device allocation"). Any executor returning
Validity::Array from the GPU hit this; the MaskedExecutor test caught it.
Also call the executors directly in the nullable RunEnd tests. Going through
execute_cuda silently falls back to CPU for a host-resident array, so those
tests passed without ever running the new runend_bool kernel.
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tible vortex.sparse has no CUDA decode kernel, and only_cuda_compatible already excluded the integer and float sparse schemes. The string variant was missed, so Euro2016 failed the GPU compression benchmark with "No CUDA kernel for encoding vortex.sparse". Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The GPU compression benchmark failed on the StructListOfInts datasets with "No CUDA kernel for encoding vortex.list". The CUDA side already had ListView offset kernels and an Arrow device export path, but nothing produced a device-resident ListView from the compressed List encoding. List stores len + 1 Arrow-style offsets; its canonical form stores one offset and one size per list. Decode the elements on the GPU and derive the view pair from the offsets with a single kernel, writing both outputs from one thread. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
into_host had no Canonical::List arm, so it hit its todo! fallback with "list(i32) not implemented" as soon as a ListViewArray was produced on the GPU. Copy the elements, offsets, and sizes children back to the host alongside the validity bitmap. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rationale for this change
--gpu-decompressincompress-benchwas gated behind an incremental allow-list holding asingle entry (
TPC-H l_comment canonical), so the GPU compression benchmark only ever measuredone dataset. Widening it to the whole suite surfaced six independent gaps in the GPU decode path,
each fixed here. The benchmark now runs all 17 datasets end to end on the GPU.
What changes are included in this PR?
Benchmark scope
gpu_decompress_benchmarksallow-list.--gpu-decompressnow runs every dataset inthe suite:
taxi, the Public BI sets, both TPC-Hl_commentvariants, theStructListOfIntswide-table variants, plus
airqualityandrplace.shells out to it, and the CPU benchmark runner already did this.
GPU decode gaps found by the widened suite
DateTimePartsdispatched throughmatch_each_signed_integer_ptype!, panicking with"Unsupported ptype u16" on
taxi. Compression picks the narrowest ptype per component and theCPU decoder already accepts any integer ptype, so match that and generate the kernel for every
signed and unsigned width.
RunEndbailed when values carriedValidity::Array. The error claimed a CPU fallback, butexecute_cudacan only fall back while all buffers are host-resident, so a device-resident scanfailed outright. New
runend_boolkernel expands the per-run validity bitmap through the runmapping, one output byte per thread.
vortex.masked. NewMaskedExecutor: aMaskedArrayis a child carrying nonulls plus the bitmap that supplies them, so decode both on the GPU and attach the mask.
vortex.list. NewListExecutorandlist_viewskernel deriving theListViewoffset/size pair fromList'slen + 1Arrow offsets.only_cuda_compatible()excluded the integer and float sparse schemes but missedstring::NullDominatedSparseScheme, so the CUDA-compatible compressor still emittedvortex.sparse(which has no GPU decoder) for string columns.into_hostcopied data buffers off the device but leftValidity::Arraybitmaps on it("unwrap_host called for Device allocation"), and had no
Canonical::Listarm at all.Tests
DateTimePartscomponents, RunEnd validity expansion across byteboundaries, masked validity, and list decode (contiguous, empty, and nullable).
execute_cudasilentlyfalls back to CPU for a host-resident array, so they passed without ever running the GPU kernel.
What APIs are changed? Are there any user-facing changes?
No public library API changes.
compress-bench --gpu-decompressno longer filters the datasetlist, and three encodings (
vortex.masked,vortex.list, and RunEnd with per-element validity)now decode on the GPU instead of erroring.
Checks
cargo clippy -p vortex-cuda -p vortex-btrblocks -p compress-bench --all-targets,cargo +nightly fmt --all,cargo test -p vortex-btrblocks --lib builder, andyamllint --strictall pass locally.CUDA tests(plus memcheck, initcheck, synccheck) pass on real hardware.One thing worth a reviewer's judgement: the GPU path now downloads
airqualityandrplacefrompcodec's public S3 bucket on every run. The CPU-side exclusion of those two exists to avoid
creating egress charges for pcodec, so this may want caching rather than a standing CI cost.