Skip to content

Optimize hash full join - #23521

Open
PointKernel wants to merge 8 commits into
NVIDIA:mainfrom
PointKernel:optimize-hash-full-join
Open

Optimize hash full join#23521
PointKernel wants to merge 8 commits into
NVIDIA:mainfrom
PointKernel:optimize-hash-full-join

Conversation

@PointKernel

@PointKernel PointKernel commented Aug 4, 2026

Copy link
Copy Markdown
Member

Description

This PR tracks matched right-table rows during hash full join retrieval, eliminating output-sized temporary storage and a subsequent scatter when finding unmatched rows. It also reserves space for the right-side complement and fixes full_join_size when the left table is empty.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@copy-pr-bot

copy-pr-bot Bot commented Aug 4, 2026

Copy link
Copy Markdown

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.

@github-actions github-actions Bot added the libcudf Affects libcudf (C++/CUDA) code. label Aug 4, 2026
@PointKernel PointKernel added Performance Performance related issue non-breaking Non-breaking change improvement Improvement / enhancement to an existing function labels Aug 4, 2026
@PointKernel

Copy link
Copy Markdown
Member Author

/ok to test 1973121

@PointKernel
PointKernel marked this pull request as ready for review August 4, 2026 21:45
@PointKernel
PointKernel requested a review from a team as a code owner August 4, 2026 21:45
@PointKernel
PointKernel requested review from bdice and qbacpey August 4, 2026 21:45
@PointKernel PointKernel added the 3 - Ready for Review Ready for review by team label Aug 4, 2026
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 41dc4d9c-c136-43f9-b2bd-82fbf0b3bf77

📥 Commits

Reviewing files that changed from the base of the PR and between a70dbd8 and b53a5ab.

📒 Files selected for processing (1)
  • cpp/src/join/join_utils.cu
🚧 Files skipped from review as they are similar to previous changes (1)
  • cpp/src/join/join_utils.cu

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved full-join handling to consistently include unmatched rows from the right-hand table.
    • Corrected full-join output sizing when the left-hand table is empty.
    • Improved match tracking and output finalization while preserving existing behavior for other join types.
  • Tests

    • Added coverage confirming that full joins with an empty left-hand table return all right-hand rows with correctly sized index results.

Walkthrough

Full hash joins now record matched right-table rows in a device buffer. Full-join sizing and finalization use this buffer to count and append unmatched right rows. Related join paths pass the updated finalization argument.

Changes

Full-join match tracking

Layer / File(s) Summary
Probe-time right-row match tracking
cpp/src/join/hash_join/dispatch.cuh, cpp/src/join/hash_join/retrieve_impl.cuh
Full joins allocate right-row match flags. Probe output marks matched rows and passes the flags to sizing and finalization.
Match-based full-join sizing
cpp/src/join/hash_join/full_join_size_impl.cu, cpp/src/join/hash_join/size_impl.cuh
Full-join sizing counts unmatched right rows from match flags and removes the unused memory-resource parameter.
Full-join finalization and integration
cpp/src/join/join_common_utils.hpp, cpp/src/join/join_utils.cu, cpp/src/join/conditional_join.cu, cpp/src/join/mixed_join.cu, cpp/tests/join/join_tests.cpp
Finalization accepts optional match flags, validates their size, and compacts unmatched rows. Related join paths pass the new argument, and the empty-left test checks output sizes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: qbacpey

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: optimizing hash full joins.
Description check ✅ Passed The description accurately explains the hash full-join optimization, right-row match tracking, storage reduction, and empty-left fix.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
cpp/tests/join/join_tests.cpp (1)

1717-1723: 📐 Maintainability & Code Quality | 🔵 Trivial

Verify the required code-owner approvals.

This file matches cpp/**/*.cpp. Obtain at least two approvals from cudf-cpp-codeowners before merge.

As per coding guidelines, changes to libcudf C++ files require at least two approvals from cudf-cpp-codeowners.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/tests/join/join_tests.cpp` around lines 1717 - 1723, Obtain at least two
approvals from the cudf-cpp-codeowners group for the changes in the C++ test
file before merging.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/src/join/hash_join/full_join_size_impl.cu`:
- Around line 20-24: Update the device lambda predicate passed to count_if in
the full join size implementation to explicitly declare its return type as bool,
while preserving its existing is_matched == 0 condition.
- Around line 50-51: Update the right_matches allocation in the full-join size
implementation to use cudf::get_current_device_resource_ref() instead of mr. If
mr is no longer referenced, remove it from the internal interface or explicitly
mark it unused while preserving the existing allocation behavior.

In `@cpp/src/join/join_common_utils.hpp`:
- Around line 75-80: Reorder finalize_full_join so right_matches precedes stream
and mr, remove its default argument, and update the Doxygen parameter order. In
cpp/src/join/join_utils.cu:91-92 and cpp/src/join/mixed_join.cu and
cpp/src/join/conditional_join.cu, pass {} explicitly for no-flag calls; in
cpp/src/join/hash_join/retrieve_impl.cuh:216-218, update the caller to the same
argument order.

---

Nitpick comments:
In `@cpp/tests/join/join_tests.cpp`:
- Around line 1717-1723: Obtain at least two approvals from the
cudf-cpp-codeowners group for the changes in the C++ test file before merging.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: aae2eb87-9bef-4a0a-a544-63a0a1210c35

📥 Commits

Reviewing files that changed from the base of the PR and between 5ba02d1 and 1973121.

📒 Files selected for processing (6)
  • cpp/src/join/hash_join/dispatch.cuh
  • cpp/src/join/hash_join/full_join_size_impl.cu
  • cpp/src/join/hash_join/retrieve_impl.cuh
  • cpp/src/join/join_common_utils.hpp
  • cpp/src/join/join_utils.cu
  • cpp/tests/join/join_tests.cpp

Comment thread cpp/src/join/hash_join/full_join_size_impl.cu
Comment thread cpp/src/join/hash_join/full_join_size_impl.cu Outdated
Comment thread cpp/src/join/join_common_utils.hpp Outdated
@PointKernel

Copy link
Copy Markdown
Member Author

NVBench comparison: hash full join

Reference: PR base at 5ba02d13606e5a3f43eddb3566d43124e1c4950c; comparison: PR head at 1973121bf91afa61364c620b4a3d8a2845b16919. Both were built from the same isolated worktree and CMake build directory. Hardware: NVIDIA GH200 480GB, CUDA 13.3, driver 580.95.05.

Coverage: full_join spans INT32, INT64, FLOAT32, FLOAT64, STRING, LIST, and STRUCT; nullable/non-nullable inputs, 1–3 keys, and 10k/100k table sizes. high_multiplicity_full_join covers INT32 hash joins, nullable/non-nullable inputs, both null modes, 1–3 keys, 10k/100k table sizes, and multiplicities 100 and 1,000. Meaningful result: 24 faster, 0 slower, and 174 within the 5%/noise threshold.

Command: nvbench/scripts/nvbench_compare.py --threshold-diff 0.05 <base> <head>. Ref is the PR base and Cmp is this change. The table contains rows with at least a 5% absolute difference. The final “Failure” count means a difference above measured noise in either direction, including FAST; it is not a regression count.

full_join

high_multiplicity_full_join

[0] NVIDIA GH200 480GB

Nullable NullEquality DataType Algorithm num_keys left_size right_size multiplicity skip_large_sizes Ref Time Ref Noise Cmp Time Cmp Noise Diff %Diff Status
0 NULLS_EQUAL INT32 HASH 1 100000 10000 100 1 1.448 ms 0.96% 1.317 ms 1.36% -131.465 us -9.08% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 2 100000 10000 100 1 1.667 ms 1.00% 1.539 ms 0.85% -128.306 us -7.70% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 3 100000 10000 100 1 1.940 ms 0.59% 1.809 ms 0.68% -130.922 us -6.75% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 1 100000 10000 1000 1 10.338 ms 0.43% 9.006 ms 0.42% -1332.040 us -12.88% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 2 100000 10000 1000 1 11.861 ms 0.37% 10.525 ms 0.36% -1335.935 us -11.26% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 3 100000 10000 1000 1 13.699 ms 0.35% 12.369 ms 0.37% -1330.212 us -9.71% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 1 100000 100000 1000 1 10.720 ms 0.46% 9.999 ms 0.38% -721.580 us -6.73% 🟢 FAST
0 NULLS_EQUAL INT32 HASH 2 100000 100000 1000 1 13.126 ms 0.41% 12.378 ms 0.30% -748.042 us -5.70% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 1 100000 10000 100 1 1.466 ms 0.93% 1.341 ms 0.94% -125.012 us -8.53% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 2 100000 10000 100 1 1.683 ms 0.71% 1.557 ms 0.78% -125.930 us -7.48% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 3 100000 10000 100 1 1.957 ms 0.60% 1.832 ms 0.72% -124.322 us -6.35% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 1 100000 10000 1000 1 10.397 ms 0.50% 9.042 ms 0.43% -1355.340 us -13.04% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 2 100000 10000 1000 1 11.926 ms 0.46% 10.559 ms 0.36% -1367.305 us -11.46% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 3 100000 10000 1000 1 13.784 ms 0.34% 12.407 ms 0.32% -1376.847 us -9.99% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 1 100000 100000 1000 1 10.778 ms 0.50% 10.031 ms 0.43% -747.009 us -6.93% 🟢 FAST
0 NULLS_UNEQUAL INT32 HASH 2 100000 100000 1000 1 13.171 ms 0.32% 12.411 ms 0.28% -760.036 us -5.77% 🟢 FAST
1 NULLS_EQUAL INT32 HASH 1 100000 10000 100 1 25.294 ms 0.50% 23.322 ms 0.55% -1972.686 us -7.80% 🟢 FAST
1 NULLS_EQUAL INT32 HASH 3 100000 10000 100 1 2.467 ms 0.77% 2.339 ms 0.77% -128.439 us -5.21% 🟢 FAST
1 NULLS_EQUAL INT32 HASH 1 100000 10000 1000 1 34.285 ms 0.49% 31.024 ms 0.73% -3261.818 us -9.51% 🟢 FAST
1 NULLS_EQUAL INT32 HASH 2 100000 10000 1000 1 13.797 ms 0.30% 12.276 ms 0.20% -1520.913 us -11.02% 🟢 FAST
1 NULLS_EQUAL INT32 HASH 3 100000 10000 1000 1 15.557 ms 0.39% 14.295 ms 0.43% -1262.160 us -8.11% 🟢 FAST
1 NULLS_UNEQUAL INT32 HASH 1 100000 10000 100 1 1.266 ms 0.96% 1.189 ms 0.91% -77.770 us -6.14% 🟢 FAST
1 NULLS_UNEQUAL INT32 HASH 1 100000 10000 1000 1 8.380 ms 0.38% 7.665 ms 0.30% -715.242 us -8.54% 🟢 FAST
1 NULLS_UNEQUAL INT32 HASH 2 100000 10000 1000 1 8.776 ms 0.34% 8.335 ms 0.32% -441.159 us -5.03% 🟢 FAST

Summary

  • Total Matches: 198
    • Pass (diff <= min_noise): 79
    • Unknown (infinite noise): 0
    • Failure (diff > min_noise): 119

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

Labels

3 - Ready for Review Ready for review by team improvement Improvement / enhancement to an existing function libcudf Affects libcudf (C++/CUDA) code. non-breaking Non-breaking change Performance Performance related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants