Atomics
When many threads write the same element — histograms, counters, scatter patterns — declare the buffer with
Atomic elements and use the atomic intrinsics:
use system.gpu
use system.gpu.atomic
fn main()
gpu var hist = Array<Atomic<u32>, 256>()
forall i in 0..147456
atomic_add(hist, i % 256, 1 as u32)
let host = hist
let bucket_0 = host[0]
let bucket_1 = host[1]
println(f"bucket_0={bucket_0} bucket_1={bucket_1}")
Output: bucket_0=576 bucket_1=576 — 147,456 threads increment 256 buckets concurrently, and
every increment lands (147456 / 256 = 576).
Atomic<i32> and Atomic<u32> support
atomic_add, atomic_sub, atomic_max, atomic_min,
atomic_and, atomic_or, atomic_xor, atomic_exchange, and
atomic_compare_exchange, each taking the buffer, the element index, and the operand
(use system.gpu.atomic). Calling one on a plain buffer, or from host code, is rejected. Reading
the result is the ordinary readback: let host = hist yields a plain host array.
See the Particle Flow demo for atomics driving a real scatter workload.