Replace hash groupby internals with HashCSR - #24050
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (24)
💤 Files with no reviewable changes (17)
Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review. 📝 SummarySummary by CodeRabbit
WalkthroughHash groupby now uses HashCSR to create grouped rows and a new single-pass aggregation pipeline. Obsolete cuco-based grouping, shared-memory, global-memory, mapping-index, and sparse-output implementations are removed. ChangesHash groupby migration
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~60 minutes Merge Risk: ⚪ Minimal · up to No concrete current-head issue remains from the finalized findings; the PR is mergeable after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 5.56% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 36 functions across 4 files. (3 skipped: 3 unsupported.)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
|
Groupby benchmarks vs
Slower cases: 4 to 8 groups with 8 aggregations, variance on ~20-row groups with 50% nulls, a single sum at 100M rows, and string keys at 84K groups without nulls. Peak memory is unchanged for distinct keys and 15 to 40% higher when aggregating. groupby_max_cardinality (20M rows, 3 int32 key columns, MAX): 56 faster, 0 slower, 0 same
groupby_max_cardinality, extra axis: 1 to 8 groups: 0 faster, 6 slower, 2 same
groupby_max_cardinality, extra axis: 200K to 2M groups: 4 faster, 2 slower, 0 same
complex_int_keys: 20 faster, 0 slower, 0 same
complex_mixed_keys: 36 faster, 4 slower, 0 same
groupby_max: 35 faster, 1 slower, 0 same
groupby_struct_keys: 18 faster, 0 slower, 0 same
groupby_m2_var_std: 42 faster, 6 slower, 0 same
groupby_m2_var_std, extra axis: 32 to 200 rows per group: 13 faster, 7 slower, 0 same
sum: 6 faster, 2 slower, 0 same
no_requests: 3 faster, 0 slower, 1 same
|
|
Groupby benchmarks vs
Since 67c719a: hot table slots are read through L1; for 2M+ rows with keys up to 32 bytes the table is sized from a sampled distinct-key estimate (full-size rebuild if it falls short); groups averaging under 128 rows are packed several per block via the segmented-reduce size hint, replacing
Slower than groupby_max_cardinality, 20 to 1M groups: 54 faster, 1 slower, 1 same
groupby_max_cardinality, 1 to 16 groups: 18 faster, 2 slower, 0 same
groupby_max_cardinality, 2M to 5M groups: 8 faster, 0 slower, 0 same
complex_int_keys: 20 faster, 0 slower, 0 same
complex_mixed_keys: 33 faster, 7 slower, 0 same
groupby_max: 31 faster, 5 slower, 0 same
groupby_struct_keys: 18 faster, 0 slower, 0 same
groupby_m2_var_std, default axes: 48 faster, 0 slower, 0 same
groupby_m2_var_std, 32 to 1000 rows per group: 56 faster, 0 slower, 0 same
sum: 7 faster, 1 slower, 0 same
no_requests: 3 faster, 0 slower, 1 same
|
Description
This PR replaces the hash groupby internals with a HashCSR build followed by CUB reductions, in the spirit of #23640 for hash join. Rows are grouped by a single probe pass that gives every row a slot and a rank, the occupied slots are compacted into groups, and a fill pass produces the grouped row order. For inputs of two million rows or more with keys up to 32 bytes, the table is sized from a sampled estimate of the number of distinct keys rather than the row count, with a bounded probe that falls back to a slot per row when the estimate is short; this keeps the table cache-resident and roughly halves peak memory on low- and mid-cardinality inputs.
Aggregations are
DeviceSegmentedReducecalls over the grouped order. Groups averaging under 128 rows are packed several per block through the dispatch's segment-size hint (one thread or one 8-lane sub-warp per group), larger groups get a block each, and groups longer than one chunk are reduced in two levels. Nullable aggregations carry the group validity in the accumulator, so a result and its null mask come out of one pass, and the sums behind MEAN, M2, VARIANCE and STD are fused into one reduction.This removes the shared-memory aggregation kernel, the block-local mapping kernel, and the dense and sparse global-memory atomic paths (about 600 lines net). All dispatch is on the host, and because reductions no longer need atomics, decimal128 MIN/MAX and fixed-point SUM_OVERFLOW now take the hash path instead of the sort-based one.
Checklist