Bank Conflict
When threads in a warp access different addresses in the same shared memory bank at once, forcing their accesses to be serialized.
A bank conflict happens when several threads in a warp simultaneously request different addresses within the same bank of shared memory. The conflicting accesses are serialized, cutting memory throughput by an integer factor and preventing the kernel from saturating memory bandwidth.
How shared memory banks work#
Like other SRAM cache memories, the shared memory in a Streaming Multiprocessor is split into groups called banks. Banks can be accessed simultaneously, which raises bandwidth.
On GPUs there are 32 banks, each 4 bytes wide. Consecutive 32-bit words (not 64-bit; GPUs were designed around 32-bit floats and integers) map to consecutive banks:
Address: 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C ... 0x7C
Bank: 0 1 2 3 4 5 6 7 ... 31
Address: 0x80 0x84 0x88 0x8C 0x90 0x94 0x98 0x9C ... 0xFC
Bank: 0 1 2 3 4 5 6 7 ... 31
Addresses 32 × 4 = 128 bytes apart map to the same bank. Shared memory is roughly kilobyte scale, so many addresses share each bank.
Conflict-free access#
When threads read sequential elements, each thread in the warp hits a different bank:
__shared__ float data[1024]; // array in shared memory
// all 32 threads access consecutive elements of data
int tid = threadIdx.x;
float value = data[tid]; // address LSBs: 0x00, 0x04, 0x08, ...
All 32 accesses complete in one memory transaction, as on the left of the figure.
A 32-way conflict#
Now suppose the threads read a column of a row-major shared memory array with 32 elements per row:
float value = data[tid * 32]; // address LSBs: 0x000, 0x080, 0x100 ...
// recall: floats are 4 bytes wide
Every access lands in Bank 0, as on the right of the figure. The accesses are serialized, a 32× increase in latency, from on the order of ten cycles to on the order of hundreds. Transposing the shared memory array fixes this conflict. For more techniques, see the Introduction to CUDA Programming and Performance Optimization talk from GTC 2024.
Key idea Only different addresses in the same bank conflict. If threads read the exact same address, the data can be multicast or broadcast and no conflict need occur.
Related#
- Memory coalescing — the equivalent access-pattern concern for global memory.
- Shared memory — the memory space that is banked.
- Memory bandwidth — what bank conflicts prevent you from saturating.