docs / GPU Programming / Atomics

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.