Skip to content

Batch non-null STRING materialization in partition - #7

Draft
res-life wants to merge 1 commit into
mainfrom
perf/partition-batched-strings-draft
Draft

res-life wants to merge 1 commit into
mainfrom
perf/partition-batched-strings-draft

Conversation

@res-life

@res-life res-life commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner

Description

Multi-column STRING focus: 1.198x event speedup, or 16.6% lower partition time, across the 117 large synthetic STRING fixtures defined below.

cudf::partition prepares and copies STRING columns separately even when its scatter map is a complete permutation. Batch sliced character-size readback and descriptor preparation, reuse prefix-scan scratch, and copy eligible columns in one character-copy launch. Sizing, offsets and character copy share the same descriptor/allocation flow and form one materialization change.

Independent split of NVIDIA/cudf#25154. It consumes scatter_map[input] = output and works with the existing map builder; it has no dependency on the rank/scan split.

CPU-only heuristic: 1,024 <= N <= 4,194,304 (16 MiB full-width row-map budget), 2 <= partitions <= 256, 2–65,535 top-level STRING columns, zero actual nulls, INT32 input offsets, and the default offset64 threshold. All other inputs retain generic scatter. Output-size/offset-width correctness guards remain. Initial PoC regressions at 10M rows and configured lower thresholds motivated the conservative declines; device length/skew samples are not used for dispatch.

364 additions + 1 deletions = 365 changed lines, including tests.

Companion independent draft: #8; both target main and neither depends on the other.

Performance

Primary workload: multi-column STRING

Across 117 large multi-column STRING fixtures, this PR gives 1.198x event-time speedup (16.6% lower partition time) and 1.198x wall-time speedup. This is the primary workload focus; the all-type aggregate is retained below as a regression/control result.

Scope: regular synthetic STRING tables with at least 1M rows, 2+ STRING columns and 2–256 partitions. Include every fixture in that scope, including nullable inputs and cases declined by this PR's heuristic. Baseline is 65b9b3c222 on NVIDIA L4; these are standalone cuDF partition microbenchmarks, not application-level benchmark results, and not incremental speedups over the complete NVIDIA#25154 implementation. Each fixture has equal weight in the geometric mean.

STRING column count Cases Event speedup Partition time reduction Wall speedup
2 53 1.210x 17.4% 1.210x
3 16 1.374x 27.2% 1.373x
4 20 1.145x 12.7% 1.144x
10 28 1.124x 11.1% 1.124x

Column-count groups contain different row/length/skew mixes; this table is not an isolated column-count scaling experiment.

Configured maximum string length (bytes) Cases Event speedup Partition time reduction Wall speedup
1–8 8 1.511x 33.8% 1.509x
9–128 67 1.214x 17.6% 1.214x
129–512 42 1.123x 11.0% 1.123x
Separate long-tail generator: mostly 0–8, max 512 4 1.425x 29.8% 1.422x

The regular-generator maximum is not a fixed per-row length. The long-tail row is a separate set, excluded from the 117-case headline. Nullable multi-STRING fixtures alone: 13 cases, 0.998x event speedup; this PR retains generic scatter for actual nulls.

Paired multi-STRING examples

Three alternating-order rounds, 30 samples per library per round. Times are medians of round medians; speedups are paired-round geometric means. The rows below are all five simultaneous-admission STRING cases in the final interaction cohort. The combined column includes both PRs; it is not this PR alone.

Rows / STRING columns / max bytes / partitions / map Baseline event ms This PR event ms This PR event speedup This PR wall speedup #7 + #8 event speedup
1,000,000 / 2 / 128 / 2 / 90% hot 2.8375 2.6071 1.089x 1.089x 1.775x
1,000,000 / 2 / 128 / 2 / uniform 2.9476 2.6029 1.131x 1.131x 1.839x
1,000,000 / 4 / 512 / 2 / uniform 14.0319 12.2982 1.142x 1.142x 1.411x
1,000,000 / 2 / 512 / 256 / 90% hot 7.3518 6.5510 1.128x 1.128x 1.467x
1,000,003 / 2 / long-tail ≤512 / 2 / 90% hot 1.3690 1.0122 1.342x 1.339x 4.223x

Across all seven interaction fixtures, no combined result declined by more than 5% against the best standalone version. Small-input retained-path latency flags remain documented below; these results do not establish universal per-case improvement.

Full matrix, retained-path flags and validation methodology
Measured subset Cases Event geomean speedup Wall geomean speedup
Original workloads 348 1.103x 1.101x
All final screening fixtures 497 1.083x 1.084x
Heuristic admits 100 1.486x 1.476x
Heuristic declines 397 1.000x 1.003x

Original heuristic families, with additional controls included:

Scenario family Cases Event speedup Wall speedup
Fixed width, no nulls 102 1.001x 1.002x
Fixed width, dense nulls (75%+) 45 1.009x 1.009x
STRING, no nulls 138 1.180x 1.179x
Empty / identity controls 47 0.999x 1.018x
Small inputs / partition boundary 88 1.190x 1.183x
Fixed width, other nulls 25 1.003x 1.003x
Uniform payload / zero columns 10 1.114x 1.109x
STRING, nullable 13 0.998x 0.998x
Mixed 13 1.009x 1.009x
Nested (LIST / STRUCT) 16 0.993x 0.994x

Screening: 0 admitted fixtures exceeded a 5% event or wall slowdown; 0 fixtures increased measured device peak by the 1% + 4 KiB reporting threshold. Focused validation repeated 41 selected fixtures in three alternating-order rounds of 30 samples per variant (baseline and this split); a separate interaction cohort compares baseline, each split and both. Repeated material slowdowns (>5%,>5us, at least 2 rounds): 1. All >5% ratio changes are retained in the report, including sub-5us changes.

Representative paired results (median of round medians; speedups use paired-round geometric means):

Fixture (N/P/C; length or width; map) Baseline event ms This PR event ms Event speedup Wall speedup Peak MiB, baseline → PR
strings-n1000003-p2-c2-w8-l129-z0-m0-d3-s7 2.8457 2.6782 1.064x 1.064x 172.82 → 134.53
strings-n1000000-p256-c2-w8-l128-z0-m0-d2-s0 2.8672 2.6552 1.094x 1.095x 171.99 → 133.69
strings-n1024-p200-c10-w8-l64-z0-m0-d0-s0 1.2621 0.1608 7.382x 7.127x 0.40 → 0.36
strings-n1024-p2-c10-w8-l64-z0-m0-d0-s0 1.2467 0.1608 7.781x 7.492x 0.40 → 0.36

Retained-path cases flagged by the repeat rule (these are not admitted by the new heuristic; causality remains unresolved):

Fixture Baseline event ms This PR event ms Paired event speedup Wall speedup
fixed-n1024-p256-c1-w4-l0-z0-m1-d0-s7 0.1024 0.1313 0.749x 0.756x

Small-input end-to-end nonregression is not established for every fixture. The full screen and paired repeats retain their slow cases above. Additional baseline A/A controls used CPU3, four rotated rounds and 100 samples on 13 selected fixtures; identical-baseline ratios ranged roughly 0.62–1.44. For one flagged fixed-width fallback (65,537 rows,P=2,C=8,I32,all-valid masks,sliced), Nsight Compute measured approximately 118.6 us total GPU kernel time for baseline and the split variants (<0.3% difference). Final rank removes the empty-map construction; CUPTI verifies that, in this profiled case, final rank and STRING fallback have the same runtime API counts as baseline (including 144 cudaGetDevice, 24 launches and 24 allocation/free pairs). These diagnostics separate the unchanged GPU work from variable CPU/API latency; they do not prove universal end-to-end improvement. Latest-upstream-main validation and stable-host latency confirmation remain before upstream review.

These drafts target res-life/cudf:main at the original NVIDIA/cudf#25154 baseline 65b9b3c222, which is also the measured base. Complete partition translation units, private headers and tests match the measured JNI sources after comments, formatting and include-order normalization. Separate ports to NVIDIA main 9efdb32adbd are prepared, but no latest-upstream-main build or performance claim is made.

All validation used an existing JNI checkout and its compatible build cache: unchanged common cuDF objects, separately rebuilt partition TU and relinked library per variant. NVIDIA L4, driver 595.71.05; CUDA 12.9.1, gcc-toolset 14, Release O3, sm89, PTDS, same RMM allocator and benchmark executable. Input construction and correctness checks are outside timing. >=150 ms warmup; 15 samples per fixture for screening. Event timing spans partition and output destruction, including CPU/GPU synchronization gaps; wall time additionally includes event recording and end synchronization. Speedups are baseline/candidate (larger is better). Peak memory means output plus temporary device allocations, excluding input/context/code caches and host pinned memory.

497 measured fixtures include all 348 original workloads, plus heuristic boundaries, schema/null/offset declines, long-tail STRING lengths, nested/zero-column/empty inputs. The rows above overlap; geometric means do not imply every input improves. Raw results retain per-case timings, samples, boundaries/schema/row-hash correctness, GPU-process isolation, loaded-library and artifact hashes. Only completed accepted runs contribute. Sliced STRUCT is excluded because the frozen baseline itself throws; unsliced STRUCT and sliced LIST/STRING/fixed-width remain covered. Disabled large-STRING threshold errors are covered by unit tests.

Validation

Two added tests cover independent CPU-expected sliced permutations, embedded NULs/empty payloads, actual nulls versus all-valid masks, N=1,023/1,024/1,025 and P=2/256/257; output offset-type and overflow behavior at configured thresholds. Existing full-suite and native boundary cases cover the upper row-map budget.

  • JNI PoC full PARTITIONING_TEST: 1,870 passed, 1 existing disabled.

  • STREAM_PARTITIONING_TEST with new-testing-default stream interposition: 7 passed.

  • 12 native fixtures through memcheck, synccheck and racecheck: zero errors/hazards, including admitted STRING N=1,025 at P=2/256.

  • Combined PoC: 1,879 partition tests + 7 stream tests passed.

  • Standalone patches, both application orders, identical resulting sources, actual Git merges, formatting and whitespace checks passed.

  • No latest-upstream-main build/test claim; these fork drafts retain the validated original baseline.

  • Independently scoped change with focused tests.

  • Performance numbers and benchmark baseline/configuration recorded.

  • Latest-upstream-main build and stable-host latency validation complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant