Repository navigation
fix(arrow-select): bounds-check take_record_batch once, with a faster check_bounds for null indices - #11829
Conversation
|
run benchmark take_kernels |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
run benchmark take_kernels |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
run benchmark take_kernels |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
run benchmark take_kernels |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
🤖 Benchmark completed (GKE) | trigger Target: take_kernels Comparing fix-take-record-batch (28ad286) to 6512c6f diff Run configurationrun benchmark take_kernels
baseline:
ref: 6512c6f72214834a7e9b30c80dc09aa4e8394b56
env:
BENCH_FILTER: check bounds|take_record_batch
shards: 1
DetailsPer-runner informationtake_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-bqth6n19-8ff92dbe-5flt Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench take_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Target: take_kernels Comparing fix-take-record-batch (28ad286) to cd2f1a4 diff Run configurationrun benchmark take_kernels
baseline:
ref: cd2f1a41036f2563eb02b4f557f7fea6b1fa020f
env:
BENCH_FILTER: check bounds|take_record_batch
shards: 1
DetailsPer-runner informationtake_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-9990rfe7-f33a191e-8tm9 Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench take_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Target: take_kernels Comparing fix-take-record-batch (28ad286) to 6512c6f diff Run configurationrun benchmark take_kernels
baseline:
ref: 6512c6f72214834a7e9b30c80dc09aa4e8394b56
env:
BENCH_FILTER: check bounds|take_record_batch
RUSTFLAGS: -C llvm-args=-align-all-functions=6 -C llvm-args=-align-all-nofallthru-blocks=6
shards: 1
DetailsPer-runner informationtake_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-bqth6n19-13544216-c487 Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench take_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
🤖 Benchmark completed (GKE) | trigger Target: take_kernels Comparing fix-take-record-batch (28ad286) to cd2f1a4 diff Run configurationrun benchmark take_kernels
baseline:
ref: cd2f1a41036f2563eb02b4f557f7fea6b1fa020f
env:
BENCH_FILTER: check bounds|take_record_batch
RUSTFLAGS: -C llvm-args=-align-all-functions=6 -C llvm-args=-align-all-nofallthru-blocks=6
shards: 1
DetailsPer-runner informationtake_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-9990rfe7-b5ee8466-njp7 Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench take_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
run benchmark take_kernels |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
🤖 Benchmark completed (GKE) | trigger Target: take_kernels Comparing fix-take-record-batch (28ad286) to 01a9917 (merge-base) diff Run configurationrun benchmark take_kernels
env:
BENCH_FILTER: ^take (check bounds )?i32 1024$|take_record_batch 5 primitive
shards: 1
DetailsPer-runner informationtake_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-155is15w-5ae84a9b-5k6v Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench take_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
|
run benchmark take_kernels |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
🤖 Benchmark completed (GKE) | trigger Target: take_kernels Comparing fix-take-record-batch (28ad286) to ef1fa15 diff Run configurationrun benchmark take_kernels
baseline:
ref: ef1fa157977633f0ba21aa921f9ef3d5c669235b
env:
BENCH_FILTER: take_record_batch
shards: 1
DetailsPer-runner informationtake_kernels — shard 1/1Node: gk3-benchmark-cluster-nap-bhbuxd0n-d730891d-c8vh Instance: c4a-highmem-16 (12 vCPU / 65 GiB) uname: BENCH_COMMAND: cargo bench --features=arrow,async,test_common,experimental,object_store --bench take_kernelsCPU Details (lscpu)Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
| // Null slots usually hold in-bounds values, so first check every value with a loop that | ||
| // vectorizes, and look at validity only if that finds one out of bounds | ||
| let in_bounds = indices.values().iter().fold(true, |in_bounds, &i| { | ||
| in_bounds & (i >= T::Native::ZERO) & (i < len) |
There was a problem hiding this comment.
using bit and here is intentional to enable vectorization?
There was a problem hiding this comment.
using bit and here is intentional to enable vectorization?
Yes. This is the existing fold from #8966, moved unchanged from the no-nulls branch on main so that it also runs when the indices have nulls. #8966 links a godbolt example of the loop vectorizing.
|
Thanks for the review @Jefffrey! |
…d_batch (apache#11831) # Which issue does this PR close? - Closes apache#11824. # Rationale for this change apache#10945 is not in a release yet, so this fix should go in 60.1.0 (apache#10525). This PR changes the same lines of `take_record_batch` as apache#11829, so it should merge after apache#11829. I will rebase it then. # What changes are included in this PR? `take_record_batch` builds its result with `RecordBatch::try_new_with_options` instead of `RecordBatch::new_unchecked`, so it checks nullability as 60.0.0 did. It passes the row count so a batch with no columns still works. # Are these changes tested? `take_record_batch` had no tests of its own, only its doc example and one test through `BatchCoalescer::push_batch_with_indices`. The new `test_take_record_batch_*` tests in `arrow-select/src/take.rs` cover a null index into non-nullable primitive, string, dictionary, struct, and fixed-size list columns, indices whose validity buffer has no nulls, and a batch with no columns. The benchmark bot shows `take_record_batch` within 2% of `main` ([default](apache#11831 (comment)), [aligned](apache#11831 (comment))). # Are there any significant user-facing changes? No. This restores the 60.0.0 behavior. --------- Co-authored-by: Jefffrey <[email protected]>
Rich-T-kid
left a comment
There was a problem hiding this comment.
approving to remove from my queue (ignore)
Which issue does this PR close?
take_record_batchreads out of bounds when the first column's type has no width #11825.Rationale for this change
#10945 is not in a release yet, so this fix should go in 60.1.0 (#10525).
What changes are included in this PR?
take_record_batchnow checks the indices once against the row count withcheck_bounds, then takes every column unchecked. It used to rely on a checked take of the first column, which reads no index for some types.In local testing, the new
check_boundscall madetake_record_batchwith null indices noticeably slower, becausecheck_boundschecks null indices one at a time. So this PR also makescheck_boundsrun its vectorized loop first, and fall back to the null-aware loop only if that finds a value out of bounds. New benchmarks cover this path.Are these changes tested?
take_record_batchhad no tests of its own, only its doc example and one test throughBatchCoalescer::push_batch_with_indices. The newtest_take_record_batch*tests inarrow-select/src/take.rscover columns whose take reads no index, out-of-bounds and negative indices, null index slots holding out-of-bounds values, empty batches, and batches with no columns.On the benchmark bot, the
check_boundsoptimization makestakewith null indices 1.7-1.9x faster (default, aligned).take_record_batchis within 3% ofmain, except 5 primitive columns, which is 7-8% slower (default, aligned). Against 60.0.0 it is 1-4% faster, except string and binary columns (run).Are there any significant user-facing changes?
take_record_batchreturns an error for an out-of-bounds index. 60.0.0 panicked for most column types, and accepted the index when no column read it, for example in a batch of onlyNullcolumns.