Store#
cuda.coop.store() writes each thread’s values into a contiguous memory
tile. The algorithm determines which input ownership it expects and whether
a shared-memory exchange rearranges the values before the writes.
The explorer shows eight illustrative threads and full-tile stores. The warp-transpose variants use two four-lane teaching warps; CUDA warps have 32 lanes. Executable blocks using those variants must contain a multiple of 32 threads.
Transpose store with eight illustrative threads and two items per thread.#
Each thread begins with a consecutive pair. The exchange redistributes those values so adjacent threads can write adjacent memory locations.
Thread 0 1 2 3 4 5 6 7
Input 0,1 2,3 4,5 6,7 8,9 10,11 12,13 14,15
Writer values 0,8 1,9 2,10 3,11 4,12 5,13 6,14 7,15
Memory 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
Reading the stages#
See blocked versus striped for a compact ownership table and the index formulas used here.
The first row shows the input payload. Transpose Store algorithms may rearrange that payload in place, as in CUB; copy values before Store if they are needed later. For algorithms with an exchange, values pass through shared scratch before reaching the writer-register row. The final row shows memory positions. Select a value to follow its input thread, writer thread, and destination address.
direct and vectorize consume blocked input: thread t provides
K consecutive values beginning at logical position t * K.
Vectorization can combine adjacent values into wider stores when the
pointer, alignment, type, and item count allow it. The illustration does
not guarantee a particular instruction or memory-transaction count.
striped consumes striped input: thread t writes slot j to
t + j * T, where T is the group size. The input must already have
that ownership. transpose instead accepts blocked input and exchanges
it into striped writer registers before performing the same writes.
warp_transpose performs the corresponding exchange within each physical
warp. warp_transpose_timesliced reuses one warp’s shared scratch across
serialized exchange rounds. The writer registers then feed warp-striped
stores; the diagram does not impose a serial global-memory store schedule.
Using Store in a kernel#
This fragment uses the common API inside a Numba-CUDA-MLIR kernel that
accepts items_per_thread. Import cuda from numba_cuda_mlir,
numpy as np, and cuda.coop as coop. Launch with 128 threads and
provide at least 128 * items_per_thread source and destination elements
for each block.
block = coop.this_block()
items = coop.ThreadData(items_per_thread)
offset = cuda.blockIdx.x * 128 * items_per_thread
coop.load(block, source, items, algorithm="direct", offset=offset)
coop.store(block, destination, items, algorithm="transpose", offset=offset)
# The block's values are written in their original logical order.
# Store writes memory and returns None; items may now be rearranged.
For a partial final tile, pass valid_items to limit the stored prefix;
memory beyond that prefix remains untouched. Supply a matching valid count
when loading the input tile. See cuda.coop.store() for the parameter
contract and the cuda.coop Programming Guide for backend activation and
thread groups.