You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[libcu++] Experimental Multiply-With-Carry random engines - #12590
The PR provides cuda::experimental::mwc64x32 and cuda::experimental::mwc128x32 to <cuda/random>, implementing Sebastiano Vigna’s scrambled Multiply-With-Carry generators.
The implementation follow the RandomNumberEngine interface, support host/device execution, constant evaluation, state comparisons, and stream serialization.
No actionable comments were generated in the recent review.
Summary
Summary by CodeRabbit
New Features
Added experimental mwc64x32 and mwc128x32 random-number engines for host and device use. Both produce 32-bit values, support seeding, and can efficiently skip ahead in generated sequences. Host stream serialization is also supported.
Documentation
Added guidance on engine characteristics, seeding, performance, and partitioning random-number streams. The engines are listed as available with CCCL 3.7.0 and CUDA Toolkit 13.7.
The PR adds experimental mwc64x32 and mwc128x32 random engines to <cuda/random>. It adds engine tests, documentation, benchmarks, and SASS code-generation checks, with test and CI configuration for the new checks.
Changes: MWC engines
Layer / File(s)
Summary
Engine implementation and export libcudacxx/include/cuda/__random/mwc_engine.h, libcudacxx/include/cuda/random
The engine implements seeding, output generation, comparison, hosted stream operations, and discard. The header defines mwc64x32 and mwc128x32, and cuda/random includes it.
Engine documentation and benchmark docs/libcudacxx/extended_api/random.rst, docs/libcudacxx/extended_api/random/mwc.rst, libcudacxx/benchmarks/bench/random/mwc.cu
The Random API index links to the new page. The page describes engine properties, seeding, performance comparisons, and stream partitioning with discard. The benchmark measures both engines across selected block sizes and sample counts.
The code-generation tests check instructions for one-step calls to both engines. CMake and CI configuration register the random SASS suite.
Assessment against linked issues
Objective
Addressed
Explanation
Add mwc64x32 and mwc128x32 to <cuda/random> with random-engine operations, including seeding, generation, discard, comparison, and stream operators [#12287]
✅
Suggested reviewers:pciolkosz, griwes
Change: Feature
Merge Risk: Low · up to a4cef
The documented kernel example can compute a wrapped thread index for launches over 2^32 threads, so users who copy it would reuse streams and overwrite output. This is a narrow documentation fix and does not affect the engines themselves. It is worth correcting before merge but is not a blocker.
Security architecture risk: Minimal · up to a4cef
The new engines are explicitly noncryptographic and maintain caller-owned state. Review found no introduced security boundary bypass or privilege expansion. Invalid serialized states are rejected without changing the engine.
Retained concerns
No architecture-level concerns identified.
Security review details
Security Blast Radius
inferred — Within the inspected implementation, caller-controlled seeds and serialized words affect the supplied engine's state and outputs, rather than an identity, authorization decision, credential store, or service-wide state. Any security-sensitive downstream use would require a separate assessment.
Trust Boundaries and Controls
observed — The routed main and runtime_test functions belong to the behavioral test executable. Main ignores command-line arguments, while runtime_test invokes engine checks with fixed seeds and reference vectors; these functions do not introduce a production input boundary.
Resilience and Maintainability Implications
observed — Failed parsing or invalid state validation cannot partially replace the engine: assignment occurs only after all words are read and validated. A seed-sequence exception before generate returns similarly precedes engine assignment. These controls contain failure within the caller's operation rather than requiring rollback of shared state.
- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
There are legitimate reasons to discard (e.g. use every k'th engine output). I leave it up to you both to use nodiscard or not - consistency is probably good.
The reason will be displayed to describe this comment to others. Learn more.
I ran some brute force fuzzing tests (hundreds of millions of outputs) and they all passed.
Tested seeding, saving and restoring state, and skipping ahead, including very large skip counts.
I (read, codex) used ESBMC and Z3 for formal verification. Examples of statements successfully checked include:
Generating the next number: for every valid starting state, the returned number and every word of the updated state match the paper.
Modular addition: for every pair of reduced operands, the helper returns the correct sum with wraparound at the engine’s modulus. This includes cases where the intermediate sum exceeds the storage width.
Seed-sequence initialization: for every possible set of generated seed words, the state digits are preserved and the carry is placed within the intended safe range.
Short skips: for every valid starting state and every skip count from 0 through 15, discard(n) leaves exactly the same state as generating and ignoring n numbers.
For larger skips, the reasoning was split smaller proofs. These establish that the multiplication algorithm computes the correct modular product, and that the skip-ahead algorithm applies exactly the requested number of transitions. The mathematical argument covers every 64-bit skip count, rather than just the values tested.
There is a mistake in the docs:
the example calculates blockIdx.x * blockDim.x using 32-bit arithmetic before assigning it to a 64-bit variable. Large launches can therefore wrap around and give different threads the same index. Widen an operand before multiplying:
auto tid = static_cast<unsignedlonglong>(blockIdx.x) * blockDim.x
+ threadIdx.x;
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Closes #12287
The PR provides
cuda::experimental::mwc64x32andcuda::experimental::mwc128x32to<cuda/random>, implementing Sebastiano Vigna’s scrambled Multiply-With-Carry generators.The implementation follow the
RandomNumberEngineinterface, support host/device execution, constant evaluation, state comparisons, and stream serialization.The PR includes: