Skip to content

[cudax][cuco] Use multiply-high range reduction for probing - #12360

Merged
sleeepyjack merged 12 commits into
NVIDIA:mainfrom
sleeepyjack:cuco-probe-index
Nov 11, 2026
Merged

sleeepyjack merged 12 commits into
NVIDIA:mainfrom
sleeepyjack:cuco-probe-index

Conversation

@sleeepyjack

@sleeepyjack sleeepyjack commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Description

Port of NVIDIA/cuCollections#869 to cudax::cuco.

Open-addressing hash tables pick the first slot to probe as hash(key) % n, with n the number of buckets known only at runtime, so every lookup pays for an integer division. This PR uses a multiply-high instead, (hash * n) >> 64, which spreads a well-mixed hash just as evenly but changes which bucket each key lands in.

Codegen

Whole-kernel static SASS instruction counts for fixed_capacity_map on CUDA 13.4, sm_120, default cuda::hash (XXH64):

Kernel Modulo Multiply-high
Find, 32-bit keys 277 228
Find, 64-bit keys 281 231
Insert, 32-bit keys 481 436
Insert, 64-bit keys 517 469

Counts include setup and cold paths, excluding NOP padding; they are not instructions executed per lookup.

Performance

RTX PRO 6000 Blackwell Max-Q, CUDA 13.4, GCC 14, Release, sm_120. fixed_capacity_map find, 32/64-bit keys, occupancy 0.5/0.8/0.9, all hits and all misses. Geometric-mean GPU time change over 12 configurations per size, median of 3 runs; negative is faster.

Hasher 800K keys 8M keys 100M keys
Default (XXH64) -11.7% -8.0% -1.3%
XXH32 -5.2% -2.4% -0.4%

Insert with 100M keys is unchanged.

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

PointKernel and others added 4 commits October 30, 2026 11:33
Replace the modulo in __hash_to_index with a multiply-high range reduction,
and restrict hash and index types to unsigned integers. Containers always
index with size_t, and signed hashes were never a documented input.
Containers always index with size_t, so drop the index type parameter and
the 32-bit index test instantiations. Mark the cooperative group
make_iterator overloads device-only since tiles exist only on device.
The helper is a few lines with a single consumer, so it does not need its
own header. Drop the casts and full namespace qualifications that the
size_t signature made redundant.
Replace the modulo in initial bucket selection and double-hashing step
reduction with multiply-high range reduction (`__probe_index`), ported
from NVIDIA/cuCollections#869. Probing only needs a well-distributed
index in [0, n), not the exact remainder; this removes the 64-bit
division call from the probing path.
@copy-pr-bot

copy-pr-bot Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

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-project-automation github-project-automation Bot moved this to Todo in CCCL Oct 30, 2026
@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Progress in CCCL Oct 30, 2026
@sleeepyjack sleeepyjack self-assigned this Oct 30, 2026
@sleeepyjack sleeepyjack added cudax Feature intended for the cudax experimental library cuco cuCollections labels Oct 30, 2026
@sleeepyjack
sleeepyjack marked this pull request as ready for review October 30, 2026 23:16
@sleeepyjack
sleeepyjack requested review from a team as code owners October 30, 2026 23:16
@cccl-authenticator-app cccl-authenticator-app Bot moved this from In Progress to In Review in CCCL Oct 30, 2026
@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration

  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 22bbd61
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 87cf773c-84a6-4768-9e87-a00f55152df4
Commits

Reviewing files that changed from the base of the PR and between 08e79df and b9ad33e.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
Summary

Summary by CodeRabbit

  • Bug Fixes
    • Improved hash-to-index mapping across different hash and index widths, including hashes near the maximum value.
    • Updated bucket selection and probing steps to use consistent hash-to-index mapping.
    • Expanded coverage for all-ones hashes and final-slot allocation in dynamic- and fixed-capacity sets.
  • Changes
    • Cooperative-group iterator creation for linear probing and double hashing is now device-only.

Hash-to-index mapping now uses multiply-high range reduction for integer and two-word array hashes. Probing iterators use cuda::std::size_t indices. Cooperative-group overloads are device-only. Tests cover mapping, probing behavior, and maximum-hash cases.

Changes: Hash-to-index range reduction

Layer / File(s) Summary
Multiply-high hash mapping
cudax/include/cuda/experimental/__cuco/detail/probing_scheme_base.cuh, cudax/include/cuda/experimental/__cuco/detail/utility/hash_to_index.cuh
The new overloads map unsigned integer hashes with multiply-high arithmetic and use the high word for two-word array hashes. The previous unsigned-magnitude remainder implementation was removed.
Probing iterator integration
cudax/include/cuda/experimental/__cuco/probing_scheme.cuh
Both probing schemes require cuda::std::size_t capacity indices and use the new mapping. Cooperative-group iterator overloads are device-only.
Mapping and probing tests
cudax/test/cuco/utility/test_probing_scheme.cu, cudax/test/cuco/fixed_capacity_set/test_capacity.cu
Tests cover mapping endpoints and midpoints, wraparound, probing cycles, wide group offsets, and maximum-hash final-slot behavior.

Suggested reviewers: srinivasyadav18

Change: Refactor

Merge Risk: Low · previous review 57134

Document the supported array hash representation so users can choose it confidently. This is a bounded API-clarity issue and does not otherwise block merging.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 4d6375c
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: a0401527-9c80-482a-9c6e-e46e8239b8ba
Commits

Reviewing files that changed from the base of the PR and between cc12031 and 571349e.

Files selected for processing: 5

  • cudax/include/cuda/experimental/__cuco/detail/probing_scheme_base.cuh
  • cudax/include/cuda/experimental/__cuco/detail/utility/hash_to_index.cuh
  • cudax/include/cuda/experimental/__cuco/probing_scheme.cuh
  • cudax/test/cuco/fixed_capacity_set/test_capacity.cu
  • cudax/test/cuco/utility/test_probing_scheme.cu
Files with no reviewable changes: 1

  • cudax/include/cuda/experimental/__cuco/detail/utility/hash_to_index.cuh
Files skipped from review as they are similar to previous changes: 1

  • cudax/test/cuco/fixed_capacity_set/test_capacity.cu

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


Review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 4d6375c
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: d24893d6-5707-4380-a721-d2afeb51bb35
Commits

Reviewing files that changed from the base of the PR and between c75c018 and cc12031.

Files selected for processing: 1
  • cudax/include/cuda/experimental/__cuco/detail/utility/hash_to_index.cuh

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.

@PointKernel PointKernel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For reference, https://github.com/PointKernel/cccl/tree/cuco-hash-range-reduction is a cleanup that addresses most of the comments below: a size_t-only __hash_to_index with a single left-align + mul_hi path, folded into detail/probing_scheme_base.cuh, and size_t-only tests with fixed expected values. Note it uses the high word for 128-bit hashes; keeping the low word as in this PR is fine too.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


Review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 4d6375c
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: a0401527-9c80-482a-9c6e-e46e8239b8ba
Commits

Reviewing files that changed from the base of the PR and between cc12031 and 571349e.

Files selected for processing: 5
  • cudax/include/cuda/experimental/__cuco/detail/probing_scheme_base.cuh
  • cudax/include/cuda/experimental/__cuco/detail/utility/hash_to_index.cuh
  • cudax/include/cuda/experimental/__cuco/probing_scheme.cuh
  • cudax/test/cuco/fixed_capacity_set/test_capacity.cu
  • cudax/test/cuco/utility/test_probing_scheme.cu
Files with no reviewable changes: 1
  • cudax/include/cuda/experimental/__cuco/detail/utility/hash_to_index.cuh
Files skipped from review as they are similar to previous changes: 1
  • cudax/test/cuco/fixed_capacity_set/test_capacity.cu

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.

//!
//! @note `_Hash` should be a callable object type.
//!
//! @note `_Hash` must return an unsigned integer whose high bits are uniformly distributed, since the high

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor · Maintainability & Code Quality · Quick win

Supported by static analysis

Script executed:

sed -n '40,60p;140,162p' cudax/include/cuda/experimental/__cuco/probing_scheme.cuh
sed -n '40,90p' cudax/include/cuda/experimental/__cuco/detail/probing_scheme_base.cuh
rg -n 'array<uint64_t, 2>|array<::cuda::std::uint64_t, 2>|128.bit|hash requirements' cudax/include/cuda/experimental/__cuco cudax/test/cuco/utility/test_probing_scheme.cu

Repository: NVIDIA/cccl

Length of output: 4791


Script executed:

set -o pipefail
printf '%s\n' '--- public probing call sites ---'
rg -n -F --glob '*.cuh' -e '__hash_to_index' -e 'operator()' -e 'make_iterator' cudax/include/cuda/experimental/__cuco/probing_scheme.cuh cudax/include/cuda/experimental/__cuco/detail/probing_scheme_base.cuh
printf '%s\n' '--- public probing declarations and calls ---'
sed -n '1,240p' cudax/include/cuda/experimental/__cuco/probing_scheme.cuh
printf '%s\n' '--- 128-bit probing test ---'
sed -n '190,260p' cudax/test/cuco/utility/test_probing_scheme.cu
printf '%s\n' '--- hash result type references and docs ---'
rg -n -F --glob '*.{cuh,cu,md,rst}' -e 'cuda::std::array<cuda::std::uint64_t, 2>' -e 'array<uint64_t, 2>' -e 'hash functor' -e 'hash result' -e 'unsigned integer' cudax docs || test "$?" -eq 1

Repository: NVIDIA/cccl

Length of output: 22189


Script executed:

set -o pipefail
printf '%s\n' '--- public 128-bit hasher declaration ---'
rg -n -F --glob '*.{h,hpp,cuh,cu,cpp,rst,md}' -e 'murmurhash3_x64_128' -e 'class hash' -e 'struct hash' -e 'using result_type' -e 'operator()' libcudacxx cudax docs | head -240
printf '%s\n' '--- exact hash implementation candidates ---'
rg --files libcudacxx cudax | rg 'hash|murmur'
printf '%s\n' '--- probing documentation and contract guidance ---'
rg -n -i --glob '*.{cuh,cu,rst,md}' 'probing.scheme|linear.probing|double.hashing|__hash_to_index|hash.*128|128.*hash' cudax docs libcudacxx | head -240

Repository: NVIDIA/cccl

Length of output: 41607


important: Document the supported two-word array hash. Both notes state that hashers must return unsigned integers. The public make_iterator overloads pass hash results to detail::__hash_to_index, which also accepts cuda::std::array<cuda::std::uint64_t, 2> with the low word first. The probing tests exercise this representation, so the current wording excludes a supported 128-bit hash result. Add this array form to both notes.

@PointKernel PointKernel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me.

sleeepyjack added a commit to sleeepyjack/cuCollections that referenced this pull request Oct 31, 2026
Match cudax::cuco (NVIDIA/cccl#12360): a 128-bit hash contributes its high 64 bits, which are then reduced like a 64-bit hash.
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 1h 44m: Pass: 100%/75 | Total: 2d 20h | Max: 1h 30m | Hits: 18%/695080

See results here.

@sleeepyjack
sleeepyjack merged commit 561b093 into NVIDIA:main Nov 11, 2026
95 checks passed
@github-project-automation github-project-automation Bot moved this from In Review to Done in CCCL Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuco cuCollections cudax Feature intended for the cudax experimental library

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants