Skip to content

Permute overhaul#3079

Draft
vinaydes wants to merge 10 commits into
NVIDIA:mainfrom
vinaydes:vd/permute-fixes
Draft

Permute overhaul#3079
vinaydes wants to merge 10 commits into
NVIDIA:mainfrom
vinaydes:vd/permute-fixes

Conversation

@vinaydes

@vinaydes vinaydes commented Jul 9, 2026

Copy link
Copy Markdown
Member

To be updated.

@copy-pr-bot

copy-pr-bot Bot commented Jul 9, 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.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Permutation operations now accept an explicit key, making results deterministic when the same key and input size are used.
    • Shuffling of samples and features now uses separate keys, improving control over randomized ordering.
  • Bug Fixes

    • Updated benchmark and test calls to use the new deterministic permutation behavior.

Walkthrough

The permutation implementation in raft::random::permute is changed from a random a/b-based index shuffle to a deterministic keyed Feistel-network permutation. A uint64_t key parameter is added throughout the public and detail API overloads, propagated into make_regression's shuffle logic (using two derived keys), and updated in benchmarks and tests to pass explicit seeds.

Changes

Keyed permutation implementation and propagation

Layer / File(s) Summary
Feistel permutation core implementation
cpp/include/raft/random/detail/permute.cuh
Adds Feistel mixer, parameter schedule, and cycle-walking index permutation logic; updates permuteKernel and permute_impl_t to use the precomputed schedule instead of random a/b values; updates detail::permute signature to accept a key.
Public API key parameter
cpp/include/raft/random/permute.cuh
Extends the primary, optional-output, and legacy raw-pointer permute overloads with a uint64_t key parameter forwarded into detail::permute, with updated documentation and copyright notice.
make_regression derived permutation keys
cpp/include/raft/random/detail/make_regression.cuh
Derives two deterministic keys from seed (direct and XOR'd) and passes them to separate permute calls for shuffling samples and features.
Benchmark and test updates for explicit seed
cpp/bench/prims/random/permute.cu, cpp/tests/random/permute.cu
Updates the benchmark call to pass an explicit 123456ULL seed and updates all test call sites (including std::nullopt variants) to pass params.seed; minor include and copyright adjustments.

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

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too generic to convey the main change in the changeset. Use a concise title that names the primary change, such as adding deterministic keyed permutation behavior to permute.
Description check ❓ Inconclusive The description is a placeholder and does not describe the changeset in a meaningful way. Replace the placeholder with a brief summary of the actual implementation changes and impacted areas.
✅ Passed checks (2 passed)
Check name Status Explanation
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
cpp/include/raft/random/permute.cuh (1)

91-96: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

HIGH: Preserve source compatibility or add deprecation coverage for the new key parameter.

Issue: Adding required uint64_t key parameters to public overloads breaks existing callers that use the previous signatures.
Why: This is a public API change in cpp/include/raft/random/permute.cuh; consider a deprecated compatibility overload or a defaulted key while callers migrate.

Suggested compatibility pattern
 void permute(raft::resources const& handle,
              raft::device_matrix_view<const InputOutputValueType, IdxType, Layout> in,
              std::optional<raft::device_vector_view<IntType, IdxType>> permsOut,
              std::optional<raft::device_matrix_view<InputOutputValueType, IdxType, Layout>> out,
              uint64_t key)
// Add a deprecated overload with the old signature that forwards to a documented default key.

As per path instructions, “For public headers under cpp/include/raft, also require Doxygen on new APIs and deprecation warnings on breaking changes.”

Also applies to: 193-203

🤖 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/include/raft/random/permute.cuh` around lines 91 - 96, The new required
key parameter on the public permute overloads breaks existing callers, so
preserve source compatibility in permute by adding a deprecated compatibility
overload with the old signature that forwards to a documented default key, or
otherwise default the new parameter where appropriate. Update the affected
permute declarations/definitions in raft::random::permute to include Doxygen for
the new API and emit deprecation warnings on the old overloads so downstream
code can migrate without a hard break.

Source: Path instructions

cpp/include/raft/random/detail/permute.cuh (1)

243-265: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

CRITICAL: Avoid launching permute kernels with zero blocks.

Issue: N == 0 makes nblks == 0, but the row-major and column-major paths still call permuteImpl, which launches <<<0, TPB, 0, stream>>>.
Why: CUDA treats zero-block launches as invalid configuration, so empty inputs fail instead of behaving as an empty permutation.

Suggested fix
 {
+  if (N == 0) { return; }
+
   auto nblks = raft::ceildiv(N, (IntType)TPB);

As per coding guidelines, “Do not launch kernels with zero blocks/threads or invalid grid/block dimensions.”

🤖 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/include/raft/random/detail/permute.cuh` around lines 243 - 265, Guard the
permute launch path in permute.cuh so empty inputs do not reach
permute_impl_t::permuteImpl with a zero grid size. In the host-side setup where
nblks is computed and the rowMajor/column-major branches call permuteImpl, add
an early return or equivalent no-op when N == 0 (or nblks == 0) before
building/using feistel_permute_params fp and launching the kernel. Keep the
existing permuteImpl specializations unchanged; the fix should only prevent
<<<0, TPB, 0, stream>>> launches from the permute wrapper.

Source: Coding guidelines

cpp/tests/random/permute.cu (1)

340-341: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add small-N permutation cases back to the test matrix. Every current PermInputs entry starts at N=32, so the N <= 1 identity path and the small non-power-of-two cycle-walk cases in the keyed Feistel permute aren’t exercised.

🤖 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/random/permute.cu` around lines 340 - 341, The PermMdspanTestD test
matrix currently only instantiates cases from inputsd starting at N=32, so it
misses the N<=1 identity path and the small non-power-of-two cycle-walk behavior
in the keyed Feistel permute. Update the test setup around
INSTANTIATE_TEST_CASE_P and the PermInputs/inputsd definitions to add back
small-N permutation cases, including N=0/1 and a few small non-power-of-two
sizes, so the existing permute coverage exercises those code paths.
🤖 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/include/raft/random/detail/permute.cuh`:
- Around line 78-83: Guard the Feistel width selection loop in the permutation
setup so it cannot overflow `uint64_t` when computing the next power of two for
large N. In the logic that updates pow2 and n, add a termination/saturation
check before shifting so the loop exits or clamps once pow2 would exceed the
representable range, and make sure any invalid or negative N values are rejected
or handled before entering this path. Keep the bijection/cycle-walking behavior
intact for supported N by preserving the current width computation semantics in
the permutation routine.

---

Outside diff comments:
In `@cpp/include/raft/random/detail/permute.cuh`:
- Around line 243-265: Guard the permute launch path in permute.cuh so empty
inputs do not reach permute_impl_t::permuteImpl with a zero grid size. In the
host-side setup where nblks is computed and the rowMajor/column-major branches
call permuteImpl, add an early return or equivalent no-op when N == 0 (or nblks
== 0) before building/using feistel_permute_params fp and launching the kernel.
Keep the existing permuteImpl specializations unchanged; the fix should only
prevent <<<0, TPB, 0, stream>>> launches from the permute wrapper.

In `@cpp/include/raft/random/permute.cuh`:
- Around line 91-96: The new required key parameter on the public permute
overloads breaks existing callers, so preserve source compatibility in permute
by adding a deprecated compatibility overload with the old signature that
forwards to a documented default key, or otherwise default the new parameter
where appropriate. Update the affected permute declarations/definitions in
raft::random::permute to include Doxygen for the new API and emit deprecation
warnings on the old overloads so downstream code can migrate without a hard
break.

In `@cpp/tests/random/permute.cu`:
- Around line 340-341: The PermMdspanTestD test matrix currently only
instantiates cases from inputsd starting at N=32, so it misses the N<=1 identity
path and the small non-power-of-two cycle-walk behavior in the keyed Feistel
permute. Update the test setup around INSTANTIATE_TEST_CASE_P and the
PermInputs/inputsd definitions to add back small-N permutation cases, including
N=0/1 and a few small non-power-of-two sizes, so the existing permute coverage
exercises those code paths.
🪄 Autofix (Beta)

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: 94b3576c-a4cd-4edd-8180-45105614b8bc

📥 Commits

Reviewing files that changed from the base of the PR and between c515501 and b57d2b6.

📒 Files selected for processing (5)
  • cpp/bench/prims/random/permute.cu
  • cpp/include/raft/random/detail/make_regression.cuh
  • cpp/include/raft/random/detail/permute.cuh
  • cpp/include/raft/random/permute.cuh
  • cpp/tests/random/permute.cu

Comment on lines +78 to +83
int n = 0;
uint64_t pow2 = 1;
while (pow2 < N) {
pow2 <<= 1;
++n;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

CRITICAL: Guard the Feistel width loop against uint64_t overflow.

Issue: For N > 2^63, pow2 <<= 1 overflows to 0, so while (pow2 < N) never terminates.
Why: A 64-bit IdxType or a negative signed N cast at Line 247 can hang the host before any CUDA error is reported.

Suggested fix
   int n         = 0;
   uint64_t pow2 = 1;
   while (pow2 < N) {
+    if (n == 63) {
+      n = 64;
+      break;
+    }
     pow2 <<= 1;
     ++n;
   }

As per path instructions, “Algorithm edge cases: keyed Feistel permutation + cycle-walking must still form a bijection over [0, N) for all supported N.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int n = 0;
uint64_t pow2 = 1;
while (pow2 < N) {
pow2 <<= 1;
++n;
}
int n = 0;
uint64_t pow2 = 1;
while (pow2 < N) {
if (n == 63) {
n = 64;
break;
}
pow2 <<= 1;
+n;
}
🤖 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/include/raft/random/detail/permute.cuh` around lines 78 - 83, Guard the
Feistel width selection loop in the permutation setup so it cannot overflow
`uint64_t` when computing the next power of two for large N. In the logic that
updates pow2 and n, add a termination/saturation check before shifting so the
loop exits or clamps once pow2 would exceed the representable range, and make
sure any invalid or negative N values are rejected or handled before entering
this path. Keep the bijection/cycle-walking behavior intact for supported N by
preserving the current width computation semantics in the permutation routine.

Source: Path instructions

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