diff --git a/cuda-oxide/crates/cuda-host/README.md b/cuda-oxide/crates/cuda-host/README.md index 7d921a8bb6..292c527a4f 100644 --- a/cuda-oxide/crates/cuda-host/README.md +++ b/cuda-oxide/crates/cuda-host/README.md @@ -20,8 +20,9 @@ mod kernels { #[kernel] pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - *c_elem = a[idx.get()] + b[idx.get()]; + *c_elem = a[i] + b[i]; } } } diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md index aff5decf2b..a5b9914bca 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md @@ -87,8 +87,9 @@ use core::ops::Mul; #[kernel] pub fn scale>(factor: T, input: &[T], mut out: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = input[idx.get()] * factor; + *out_elem = input[i] * factor; } } ``` diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/README.md index 13639ba78a..cb118a58d3 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/README.md @@ -42,8 +42,9 @@ pub fn clock_test(mut output: DisjointSlice) { #[kernel] pub fn trap_test(input: &[i32], mut output: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(output_elem) = output.get_mut(idx) { - let val = input[idx.get()]; + let val = input[i]; if val < 0 { debug::trap(); // Kernel aborts here @@ -60,8 +61,9 @@ pub fn trap_test(input: &[i32], mut output: DisjointSlice) { #[kernel] pub fn assert_test(input: &[i32], mut output: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(output_elem) = output.get_mut(idx) { - let val = input[idx.get()]; + let val = input[i]; // With message gpu_assert!(val >= 0, "Expected non-negative value"); @@ -86,11 +88,12 @@ The two forms intentionally use different failure mechanisms: #[kernel] pub fn breakpoint_test(mut output: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(output_elem) = output.get_mut(idx) { - if idx.get() == 0 { + if i == 0 { debug::breakpoint(); // cuda-gdb stops here } - *output_elem = idx.get() as i32; + *output_elem = i as i32; } } ``` @@ -101,10 +104,11 @@ pub fn breakpoint_test(mut output: DisjointSlice) { #[kernel] pub fn profiler_test(input: &[f32], mut output: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(output_elem) = output.get_mut(idx) { debug::prof_trigger::<0>(); // Region start marker - let val = input[idx.get()]; + let val = input[i]; let result = val * val; debug::prof_trigger::<1>(); // Region end marker diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/src/main.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/src/main.rs index 5b4f1fe1cc..c604dd98e6 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/src/main.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/src/main.rs @@ -49,8 +49,9 @@ //! fn scale_kernel(factor: u32, input: &[u32], mut out: DisjointSlice) { //! // 'factor' is the closure capture, passed as scalar argument //! let idx = thread::index_1d(); +//! let i = idx.get(); //! if let Some(slot) = out.get_mut(idx) { -//! *slot = input[idx.get()] * factor; +//! *slot = input[i] * factor; //! } //! } //! ``` diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/error/README.md index 2b8d3298f3..52e3e7a186 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error/README.md @@ -25,9 +25,10 @@ This is a **negative test** - it verifies that: #[kernel] pub fn valid_f64_to_f32_kernel(a: &[f64], b: &[f64], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { // Valid: explicit f64 to f32 cast - *c_elem = (a[idx.get()] + b[idx.get()]) as f32; + *c_elem = (a[i] + b[i]) as f32; } } ``` @@ -38,13 +39,14 @@ pub fn valid_f64_to_f32_kernel(a: &[f64], b: &[f64], mut c: DisjointSlice) #[kernel] pub fn unsupported_format_kernel(a: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { // INVALID: format_args! uses core::fmt which requires: // - Dynamic dispatch (dyn Trait) // - Heap allocation // - Complex runtime machinery - let _formatted = core::format_args!("{}", a[idx.get()]); - *c_elem = a[idx.get()]; + let _formatted = core::format_args!("{}", a[i]); + *c_elem = a[i]; } } ``` diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/README.md index cb8d5ce2db..eb942b55d5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/README.md @@ -19,16 +19,18 @@ Tests whether the collector correctly handles monomorphized generic kernels. Thi #[kernel] pub fn scale>(factor: T, input: &[T], mut out: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = input[idx.get()] * factor; + *out_elem = input[i] * factor; } } #[kernel] pub fn add>(a: &[T], b: &[T], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - *c_elem = a[idx.get()] + b[idx.get()]; + *c_elem = a[i] + b[i]; } } ``` @@ -98,8 +100,9 @@ pub fn saxpy + Add>( a: T, x: &[T], y: &[T], mut out: DisjointSlice ) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = a * x[idx.get()] + y[idx.get()]; + *out_elem = a * x[i] + y[i]; } } @@ -116,8 +119,9 @@ pub fn saxpy + Add>( #[kernel] pub fn map T + Copy>(f: F, input: &[T], mut out: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = f(input[idx.get()]); + *out_elem = f(input[i]); } } ``` diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/README.md index 193e0b8edc..915c46e86a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/README.md @@ -18,8 +18,8 @@ Demonstrates the `#[device]` attribute for helper functions that are called from #[device] pub fn vecadd_device(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - let i = idx.get(); *c_elem = a[i] + b[i]; } } @@ -90,11 +90,12 @@ fn clamp(x: f32, lo: f32, hi: f32) -> f32 { #[kernel] pub fn apply_clamp(input: &[f32], mut out: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { // Call the device function by its original name. The macro // expands this to the reserved internal symbol behind the // scenes; users never type the mangled name themselves. - *out_elem = clamp(input[idx.get()], 0.0, 1.0); + *out_elem = clamp(input[i], 0.0, 1.0); } } ``` diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/README.md index e20dd4890a..15ed94e347 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/README.md @@ -18,8 +18,9 @@ Tests passing closures from host code to generic GPU kernels. This enables funct #[kernel] pub fn map T + Copy>(f: F, input: &[T], mut out: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = f(input[idx.get()]); + *out_elem = f(input[i]); } } ``` diff --git a/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs b/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs index 8564f84dbe..dcfc592fc2 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs @@ -246,8 +246,9 @@ //! #[kernel] //! pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { //! let idx = thread::index_1d(); +//! let i = idx.get(); //! if let Some(c_elem) = c.get_mut(idx) { -//! *c_elem = a[idx.get()] + b[idx.get()]; +//! *c_elem = a[i] + b[i]; //! } //! } //! diff --git a/cuda-oxide/cuda-oxide-book/compiler/mir-importer.md b/cuda-oxide/cuda-oxide-book/compiler/mir-importer.md index d6c3281ade..181a824718 100644 --- a/cuda-oxide/cuda-oxide-book/compiler/mir-importer.md +++ b/cuda-oxide/cuda-oxide-book/compiler/mir-importer.md @@ -401,8 +401,9 @@ pieces connect. Here is a vector addition kernel: #[kernel] pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - *c_elem = a[idx.get()] + b[idx.get()]; + *c_elem = a[i] + b[i]; } } ``` diff --git a/cuda-oxide/cuda-oxide-book/gpu-programming/closures-and-generics.md b/cuda-oxide/cuda-oxide-book/gpu-programming/closures-and-generics.md index 7055e8100c..8826017482 100644 --- a/cuda-oxide/cuda-oxide-book/gpu-programming/closures-and-generics.md +++ b/cuda-oxide/cuda-oxide-book/gpu-programming/closures-and-generics.md @@ -342,8 +342,9 @@ pub fn apply_transform(input: &[f32], mut out: DisjointSlice) { clamped * clamped }; + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = transform(input[idx.get()]); + *out_elem = transform(input[i]); } } ``` diff --git a/cuda-oxide/cuda-oxide-book/gpu-programming/error-handling-and-debugging.md b/cuda-oxide/cuda-oxide-book/gpu-programming/error-handling-and-debugging.md index f48e28e4b5..c49bc2c7c7 100644 --- a/cuda-oxide/cuda-oxide-book/gpu-programming/error-handling-and-debugging.md +++ b/cuda-oxide/cuda-oxide-book/gpu-programming/error-handling-and-debugging.md @@ -45,8 +45,9 @@ pub fn debug_kernel(data: &[f32], mut out: DisjointSlice) { if idx.get() < 4 { gpu_printf!("Thread {} sees value {}\n", idx.get(), data[idx.get()]); } + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = data[idx.get()] * 2.0; + *out_elem = data[i] * 2.0; } } ``` @@ -81,7 +82,7 @@ the GPU. `gpu_printf!` bypasses all of this by lowering directly to a CUDA For fatal error checking on the device, use `gpu_assert!` or `debug::trap()`: ```rust -use cuda_device::{DisjointSlice, debug, gpu_assert, kernel, thread}; +use cuda_device::{DisjointSlice, gpu_assert, kernel, thread}; #[kernel] pub fn checked_kernel(data: &[f32], len: u32, mut out: DisjointSlice) { @@ -96,8 +97,9 @@ pub fn checked_kernel(data: &[f32], len: u32, mut out: DisjointSlice) { "expected non-negative input" ); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = data[idx.get()]; + *out_elem = data[i]; } } ``` diff --git a/cuda-oxide/cuda-oxide-book/gpu-programming/execution-model.md b/cuda-oxide/cuda-oxide-book/gpu-programming/execution-model.md index 7694d271f5..b014d86292 100644 --- a/cuda-oxide/cuda-oxide-book/gpu-programming/execution-model.md +++ b/cuda-oxide/cuda-oxide-book/gpu-programming/execution-model.md @@ -46,8 +46,9 @@ use cuda_device::{DisjointSlice, kernel, thread}; #[kernel] pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - *c_elem = a[idx.get()] + b[idx.get()]; + *c_elem = a[i] + b[i]; } } ``` @@ -238,8 +239,9 @@ returns `None` for out-of-bounds indices, so those threads simply do nothing: #[kernel] pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { // out-of-bounds threads skip - *c_elem = a[idx.get()] + b[idx.get()]; + *c_elem = a[i] + b[i]; } } ``` diff --git a/cuda-oxide/cuda-oxide-book/gpu-programming/kernels-and-device-functions.md b/cuda-oxide/cuda-oxide-book/gpu-programming/kernels-and-device-functions.md index 303334a50e..33f12f7b39 100644 --- a/cuda-oxide/cuda-oxide-book/gpu-programming/kernels-and-device-functions.md +++ b/cuda-oxide/cuda-oxide-book/gpu-programming/kernels-and-device-functions.md @@ -23,8 +23,9 @@ use cuda_device::{DisjointSlice, kernel, thread}; #[kernel] pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - *c_elem = a[idx.get()] + b[idx.get()]; + *c_elem = a[i] + b[i]; } } ``` @@ -152,8 +153,9 @@ fn clamp(x: f32, lo: f32, hi: f32) -> f32 { #[kernel] pub fn apply_clamp(input: &[f32], mut out: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = out.get_mut(idx) { - *out_elem = clamp(input[idx.get()], 0.0, 1.0); + *out_elem = clamp(input[i], 0.0, 1.0); } } ``` diff --git a/cuda-oxide/cuda-oxide-book/gpu-safety/the-safety-model.md b/cuda-oxide/cuda-oxide-book/gpu-safety/the-safety-model.md index ed7f98b663..80d9168fe5 100644 --- a/cuda-oxide/cuda-oxide-book/gpu-safety/the-safety-model.md +++ b/cuda-oxide/cuda-oxide-book/gpu-safety/the-safety-model.md @@ -81,8 +81,8 @@ on multiple slices: #[kernel] pub fn vecadd(a: &[f32], b: &[f32], mut c: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(c_elem) = c.get_mut(idx) { - let i = idx.get(); *c_elem = a[i] + b[i]; } } diff --git a/cuda-oxide/cuda-oxide-book/projects/async-mlp-pipeline.md b/cuda-oxide/cuda-oxide-book/projects/async-mlp-pipeline.md index 7c12483443..fb538a0bbb 100644 --- a/cuda-oxide/cuda-oxide-book/projects/async-mlp-pipeline.md +++ b/cuda-oxide/cuda-oxide-book/projects/async-mlp-pipeline.md @@ -158,12 +158,13 @@ pub fn matvec_naive( mut vec_out: DisjointSlice, ) { let row = thread::index_1d(); + let i = row.get(); if let Some(out_elem) = vec_out.get_mut(row) { let n_sz = n as usize; let mut sum = 0.0f32; let mut j = 0usize; while j < n_sz { - sum = sum + mat[row.get() * n_sz + j] * vec_in[j]; + sum = sum + mat[i * n_sz + j] * vec_in[j]; j = j + 1; } *out_elem = sum; @@ -181,8 +182,9 @@ interfaces. #[kernel] pub fn relu(input: &[f32], mut output: DisjointSlice) { let idx = thread::index_1d(); + let i = idx.get(); if let Some(out_elem) = output.get_mut(idx) { - let val = input[idx.get()]; + let val = input[i]; *out_elem = if val > 0.0f32 { val } else { 0.0f32 }; } }