Skip to content

Commit 5f9c0c5

Browse files
committed
feat: add experimental cuda-oxide fGN backend
1 parent 897ba33 commit 5f9c0c5

11 files changed

Lines changed: 1466 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ members = [
1010
"stochastic-rs-viz",
1111
"stochastic-rs-py",
1212
]
13+
# Device-only cuda-oxide kernel crate: its own `[workspace]` root (built
14+
# standalone with the cuda-oxide codegen backend to emit NVVM IR), excluded so
15+
# the umbrella workspace does not claim it as a member.
16+
exclude = ["stochastic-rs-stochastic/fgn-oxide-kernels"]
1317

1418
[workspace.package]
1519
version = "2.3.0"
@@ -90,6 +94,9 @@ cubecl = { version = "0.9.0", default-features = false }
9094
cubecl-cuda = "0.9.0"
9195
cubecl-wgpu = "0.9.0"
9296
cudarc = { version = "0.19.2", features = ["cuda-12080", "cuda-version-from-build-system"] }
97+
cuda-core = { git = "https://github.com/NVlabs/cuda-oxide.git", rev = "4a56e4220aab8ce5d085a411e7f806cebb647d14" }
98+
cuda-device = { git = "https://github.com/NVlabs/cuda-oxide.git", rev = "4a56e4220aab8ce5d085a411e7f806cebb647d14" }
99+
cuda-host = { git = "https://github.com/NVlabs/cuda-oxide.git", rev = "4a56e4220aab8ce5d085a411e7f806cebb647d14" }
93100
gpu-fft = "1.1.1"
94101
metal = "0.33.0"
95102

@@ -140,6 +147,9 @@ cubecl = { workspace = true, optional = true, default-features = false }
140147
cubecl-cuda = { workspace = true, optional = true }
141148
cubecl-wgpu = { workspace = true, optional = true }
142149
cudarc = { workspace = true, optional = true, features = [ "cuda-12080", "cuda-version-from-build-system", ] }
150+
cuda-core = { workspace = true, optional = true }
151+
cuda-device = { workspace = true, optional = true }
152+
cuda-host = { workspace = true, optional = true }
143153
flate2 = { workspace = true }
144154
gpu-fft = { workspace = true, optional = true }
145155
gauss-quad = { workspace = true }
@@ -221,6 +231,11 @@ name = "fgn_cuda_native"
221231
harness = false
222232
required-features = ["cuda-native"]
223233

234+
[[bench]]
235+
name = "fgn_cuda_oxide"
236+
harness = false
237+
required-features = ["cuda-oxide-experimental"]
238+
224239
[[bench]]
225240
name = "fgn_cuda_compare"
226241
harness = false
@@ -328,6 +343,12 @@ required-features = ["cuda-native"]
328343
[features]
329344
ai = ["dep:stochastic-rs-ai", "stochastic-rs-ai/quant"]
330345
cuda-native = ["dep:cudarc", "cudarc/cufft", "stochastic-rs-stochastic/cuda-native"]
346+
cuda-oxide-experimental = [
347+
"dep:cuda-core",
348+
"dep:cuda-device",
349+
"dep:cuda-host",
350+
"stochastic-rs-stochastic/cuda-oxide-experimental",
351+
]
331352
default = []
332353
# Experimental: opt in to the dual-stream RNG (`SimdRngDual` /
333354
# `SimdNormalDual`). ~5–11% speedup on Ziggurat-based Normal/Exp bulk

benches/fgn_cuda_oxide.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use std::hint::black_box;
2+
use std::time::Duration;
3+
4+
use criterion::BenchmarkId;
5+
use criterion::Criterion;
6+
use criterion::criterion_group;
7+
use criterion::criterion_main;
8+
use stochastic_rs::simd_rng::Unseeded;
9+
use stochastic_rs::stochastic::noise::fgn::Fgn;
10+
use stochastic_rs::traits::ProcessExt;
11+
12+
fn bench_fgn_cuda_oxide(c: &mut Criterion) {
13+
let mut group = c.benchmark_group("FGN_cuda_oxide_experimental");
14+
group.measurement_time(Duration::from_secs(3));
15+
group.warm_up_time(Duration::from_millis(700));
16+
group.sample_size(30);
17+
18+
let cases = [
19+
(4096usize, 32usize),
20+
(16384usize, 128usize),
21+
(65536usize, 128usize),
22+
];
23+
24+
for &(n, m) in &cases {
25+
let label = format!("n={n},m={m}");
26+
let fgn = Fgn::new(0.7f32, n, None, Unseeded);
27+
let _ = fgn
28+
.sample_cuda_oxide_with_module(m, "fgn_cuda_oxide")
29+
.expect("cuda-oxide warmup should succeed");
30+
31+
group.bench_with_input(BenchmarkId::new("cpu/sample_par", &label), &m, |b, &m| {
32+
b.iter(|| black_box(fgn.sample_par(m)));
33+
});
34+
35+
group.bench_with_input(
36+
BenchmarkId::new("cuda_oxide/sample", &label),
37+
&m,
38+
|b, &m| {
39+
b.iter(|| {
40+
black_box(
41+
fgn
42+
.sample_cuda_oxide_with_module(m, "fgn_cuda_oxide")
43+
.expect("cuda-oxide sampling should succeed"),
44+
)
45+
});
46+
},
47+
);
48+
}
49+
50+
group.finish();
51+
}
52+
53+
criterion_group!(benches, bench_fgn_cuda_oxide);
54+
criterion_main!(benches);

stochastic-rs-stochastic/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ gpu = ["dep:cubecl", "dep:gpu-fft"]
2626
gpu-cuda = ["gpu", "dep:cubecl-cuda"]
2727
gpu-wgpu = ["gpu", "dep:cubecl-wgpu"]
2828
cuda-native = ["dep:cudarc", "cudarc/cufft"]
29+
cuda-oxide-experimental = [
30+
"dep:cuda-core",
31+
"dep:cuda-device",
32+
"dep:cuda-host",
33+
"dep:fgn-oxide-kernels",
34+
]
2935
metal = ["dep:metal"]
3036
accelerate = []
3137
python = ["dep:pyo3", "dep:numpy", "stochastic-rs-core/python", "stochastic-rs-distributions/python"]
@@ -64,6 +70,14 @@ cubecl = { workspace = true, optional = true, default-features = false }
6470
cubecl-cuda = { workspace = true, optional = true }
6571
cubecl-wgpu = { workspace = true, optional = true }
6672
cudarc = { workspace = true, optional = true, features = ["cuda-12080", "cuda-version-from-build-system"] }
73+
cuda-core = { workspace = true, optional = true }
74+
cuda-device = { workspace = true, optional = true }
75+
cuda-host = { workspace = true, optional = true }
76+
# Device-only kernel crate (its own `[workspace]`); provides the `#[kernel]`
77+
# markers the host `cuda_launch!` calls resolve against. Built as host stubs by
78+
# a normal `cargo build`; its NVVM IR is pre-generated and embedded — see
79+
# `noise/fgn/cuda_oxide.rs`.
80+
fgn-oxide-kernels = { path = "fgn-oxide-kernels", optional = true }
6781
gpu-fft = { workspace = true, optional = true }
6882
metal = { workspace = true, optional = true }
6983
pyo3 = { workspace = true, features = ["extension-module"], optional = true }
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Device-only kernel crate for the experimental cuda-oxide fGN backend.
2+
#
3+
# This crate contains ONLY `#[kernel]` device code. It is compiled two ways:
4+
# 1. Normally (plain `cargo build`) it expands to host-side kernel markers
5+
# that `stochastic-rs-stochastic`'s `cuda_launch!` calls resolve against.
6+
# 2. Once, by the maintainer, with the cuda-oxide rustc codegen backend
7+
# (`RUSTFLAGS="-Z codegen-backend=…"` + `CUDA_OXIDE_PTX_DIR`), it emits
8+
# `fgn_oxide_kernels.ptx`. That PTX is committed and `include_str!`-ed into
9+
# the lib so downstream users run with a plain `cargo build` — no
10+
# `cargo oxide` / precompile step on their side.
11+
#
12+
# Standalone `[workspace]` so the cuda-oxide device build does not pull in the
13+
# whole stochastic-rs workspace (host-only code can't be lowered to PTX).
14+
[package]
15+
name = "fgn-oxide-kernels"
16+
version = "0.1.0"
17+
edition = "2024"
18+
license = "MIT"
19+
description = "Device-side fGN kernels for the experimental cuda-oxide backend."
20+
21+
# Not a workspace root: the umbrella `Cargo.toml` lists this path under
22+
# `[workspace].exclude`, so it builds standalone for cuda-oxide PTX generation
23+
# yet is usable as a path dependency without a "multiple workspace roots" error.
24+
25+
[lib]
26+
doctest = false
27+
28+
[dependencies]
29+
# The `#[kernel]` macro expands to code referencing all three cuda-oxide crates
30+
# (device intrinsics + host-side registration markers), so all are required even
31+
# though this crate is device-only.
32+
cuda-device = { git = "https://github.com/NVlabs/cuda-oxide.git", rev = "4a56e4220aab8ce5d085a411e7f806cebb647d14" }
33+
cuda-host = { git = "https://github.com/NVlabs/cuda-oxide.git", rev = "4a56e4220aab8ce5d085a411e7f806cebb647d14" }
34+
cuda-core = { git = "https://github.com/NVlabs/cuda-oxide.git", rev = "4a56e4220aab8ce5d085a411e7f806cebb647d14" }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[toolchain]
2+
channel = "nightly-2026-04-03"
3+
components = ["rust-src", "rustc-dev", "llvm-tools"]

0 commit comments

Comments
 (0)