GPU offload for Nassau's Milnor multiply (p = 2)#264
Conversation
Criterion benches for Milnor multiplication, module actions, and the Nassau-regime operation-by-element multiply, sharing a small harness in benches/common. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
An operation-by-element multiply that precomputes admissible matrices. It is later moved off the CPU hot path and kept as the model for the GPU port. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
An S_2-at-p=2 end-to-end timing harness with an opt-in flamegraph, a compile-time-gated multiply profiler reporting per-operation and per-launch GPU-occupancy metrics, and a trim of wasted work in the p=2 multiply hot path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
Flat, arc-swapped seqno tables (the output-indexing primitive the GPU multiply needs) with a hashmap A/B bench. Moves the admissible-matrix multiply off the CPU path, keeping it as the GPU model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
Staged CubeCL kernels (F2 xor, on-device seqno, single-R and batched multiply) wired into Nassau's get_partial_matrix, with u16-packed admissible/term transfers and parallel host marshalling. Gated behind the gpu feature; cargo check/build need no CUDA toolkit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
Compute the Nassau differential matrix once per bidegree, cache admissible-matrix enumeration across launches, keep the admissible buffers resident on-device, and release per-launch memory on a single pinned CUDA stream so cleanup actually reclaims it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
Collapse a nested if into a let-chain, drop an unused import, and repair broken/ambiguous intra-doc links (fully-qualify a cross-crate link, and demote links to private items and cube-macro-shadowed kernels to code spans). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
|
Warning Review limit reached
Next review available in: 28 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughAdds a CUDA-backed Milnor multiplication path with seqno indexing and profiling, integrates batched products into Nassau differential construction with matrix reuse, and introduces Criterion benchmarks, CUDA development configuration, end-to-end correctness tests, and timing harnesses. ChangesGPU Milnor multiplication and Nassau resolution
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Nassau as Nassau resolution
participant Differential as build_partial_matrix
participant GPU as nassau_gpu
participant CUDA as Milnor GPU kernels
participant Matrix as Differential matrix
Nassau->>Differential: request partial differential
Differential->>GPU: dispatch applicable products
GPU->>CUDA: submit batched GpuProduct records
CUDA-->>GPU: return packed F₂ output limbs
GPU->>Matrix: decode and add output rows
Matrix-->>Nassau: return differential matrix
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Drops the dev-only MILNOR_PROFILE profiling harness that guided the GPU work but has no place in the shipped code: the `profile!` macro and `profile` module (counters, occupancy metrics, report), their hot-path hooks in the multiply and in homomorphism matrix builds, the build.rs cfg wiring, and the nassau_e2e example's opt-in pprof flamegraph. The algebra's mathematical `profile` field (the Milnor sub-Hopf-algebra truncation) and the criterion benchmark suite are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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 `@ext/crates/algebra/src/algebra/milnor_algebra.rs`:
- Around line 968-986: The profiling hooks in multiply_basis_element_by_element
run for all primes but are reported as p=2-only metrics. Restrict
profile::record_call, profile::identity, profile::perterm, and
profile::scope_record to the p=2 path, or separate odd-prime data into distinct
counters; update profile::report output and counter field documentation to match
the chosen behavior.
- Around line 1955-1961: Update AdmissibleMatrix::new to handle an empty ps
slice without calling unwrap on the max result, returning a valid zero-column
matrix (or otherwise applying the type’s empty-input invariant). Adjust related
row/column initialization as needed and add a regression test covering
AdmissibleMatrix::new(&[]).
- Around line 1358-1423: Prevent concurrent compute_seqno_tables calls from
replacing a larger cached table with a smaller one. Keep the existing fast-path
check, then publish the newly built SeqnoTables using an atomic CAS/RCU-style
conditional update that only stores it when the currently cached max_degree is
absent or lower; otherwise retain the existing larger table.
In `@ext/crates/algebra/src/algebra/milnor_gpu.rs`:
- Around line 139-141: Add explicit checked conversions for all narrowing from
u32/PPartEntry to u16 in the relevant matrix/term-building code, including the
col_sums, masks, and term_pparts paths around the shown self.col_sums,
self.masks, and index.insert operations. Prefer u16::try_from(...).expect(...)
consistent with seqno_table_u32, or add equivalent bounds assertions, so values
exceeding u16::MAX fail instead of silently wrapping.
- Around line 148-908: Configure CI to run the ignored GPU hardware tests
xor_f2_matches_host, seqno_matches_index_on_gpu,
multiply_single_r_matches_reference, and multiply_batch_matches_reference on a
runner with a live CUDA device. Add the required CUDA setup and invoke the
appropriate ignored cargo tests for ext/crates/algebra, ensuring this job is
part of CI validation and clearly marked as GPU-dependent.
In `@ext/tests/nassau_gpu_timing.rs`:
- Around line 23-44: Serialize the ignored GPU timing tests so they cannot
concurrently mutate NASSAU_GPU: configure the test binary or its documented
invocation to run with a single test thread, updating the module-level
documentation command accordingly. Ensure both gpu_only_resolution_time and the
other ignored test covering lines 46–76 use this serialized execution path, and
update the safety comments to reflect the enforced single-threaded harness.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0d35a31a-47ce-4a3a-92d9-9e6a0da42cce
📒 Files selected for processing (23)
ext/Cargo.tomlext/benches/milnor_gpu_ab.rsext/crates/algebra/Cargo.tomlext/crates/algebra/benches/common/mod.rsext/crates/algebra/benches/milnor.rsext/crates/algebra/benches/module_action.rsext/crates/algebra/benches/multiplication.rsext/crates/algebra/benches/nassau_milnor.rsext/crates/algebra/benches/seqno.rsext/crates/algebra/build.rsext/crates/algebra/src/algebra/milnor_algebra.rsext/crates/algebra/src/algebra/milnor_gpu.rsext/crates/algebra/src/algebra/mod.rsext/crates/algebra/src/module/free_module.rsext/crates/algebra/src/module/homomorphism/mod.rsext/examples/nassau_e2e.rsext/flake.nixext/src/lib.rsext/src/nassau.rsext/src/nassau_gpu.rsext/tests/nassau_gpu.rsext/tests/nassau_gpu_reuse.rsext/tests/nassau_gpu_timing.rs
Cut the process archaeology that documented how the port was built rather than what the code does: the stage-by-stage narrative in the milnor_gpu module doc, the A/B benchmark figures and "measured a regression / see the commit history" notes around the admissible multiply and seqno index, and the now-dangling references to the removed GPU_KERNEL_HANDOFF.md. The design rationale that explains the current code (why seqno is GPU-only, why the admissible multiply is the GPU reference model, the stream-pinning / OOM reasoning) is kept. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
- compute_seqno_tables: guard the publish with an rcu that only replaces the cache when the new table reaches at least as far, so parallel `get_partial_matrix` builds can't shrink it out from under `seqno` (which would then index out of bounds and panic). - GPU marshalling: narrow admissible-matrix / p-part entries to u16 through a checked `narrow_u16` helper that panics loudly instead of silently wrapping if a future larger-degree run exceeds u16. - AdmissibleMatrix::new: state the non-empty-R precondition with a debug_assert instead of relying on a bare `.max().unwrap()`. - nassau_gpu_timing doc: document `--test-threads=1`, required because both ignored tests toggle the process-wide NASSAU_GPU env var. - xor_f2_on_gpu: use size_of_val for the output buffer size (clippy). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fsxqsgjoa5RWYhAvRG1bT2
Offloads the admissible-matrix Milnor multiplication at the heart of Nassau's
get_partial_matrixto the GPU via CubeCL, for the p = 2 / trivial-profile regime. Gated behind thegpufeature;cargo check/buildneed no CUDA toolkit (cudarc dlopens at runtime).Highlights:
seqnoindex tables (flat, arc-swapped) — the on-device output-indexing primitive.R→ batched), with u16-packed transfers, dedup-by-R+ prefix-sum pair decoding, and parallel host marshalling.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Performance
Bug Fixes
Tests