6.2.9 · D1GPU Architecture

Foundations — Bank conflicts in shared memory

1,650 words8 min readBack to topic

Before you can answer that question you need to own a small pile of words and symbols. The parent note throws around warp, bank, word, stride, mod, gcd, and [r][c] addressing as if you already know them. This page builds every one of them from nothing, in an order where each piece rests on the previous.


1. A thread, and a warp of 32 of them

The number that tells a thread "who am I" is written threadIdx.x. If you have 32 threads, threadIdx.x runs . We will call this number throughout.

Figure — Bank conflicts in shared memory

2. Bytes, words, and why we divide addresses by 4

To turn a byte-address into a word-number you divide by 4 and throw away the remainder:

Those marks are the floor symbol — "round down to a whole number." We need it because addresses 0, 1, 2, 3 must all collapse to word 0.

Figure — Bank conflicts in shared memory

3. The mod operation — the clock that makes banks repeat

The picture is a clock face. A clock does : after 12 you wrap back to 0. Bank assignment does : after word 31 you wrap back to bank 0.

Figure — Bank conflicts in shared memory

4. Stride — how far apart my threads reach

So thread reads word , and therefore lands in bank

This single line is the engine of the whole topic. Everything the parent note computes is this line with a specific plugged in.


5. GCD — the tool that predicts the collision count

The payoff formula the parent uses:

  • Coprime stride (): the map hits all 32 banks — a permutation, perfectly conflict-free. (This is why the odd-stride .x field access is safe.)
  • : only distinct banks are used, so threads share each one — a -way conflict.

6. [r][c] addressing — how a 2-D array becomes one number

That is why reading a column (matrix[i][col], varying the row ) has stride : it is the worst case when , and it becomes safe when you pad to (because , turning the row-step back into a friendly stride of 1 in bank-space).


Prerequisite map

Thread and threadIdx

Warp of 32 threads

Byte

4-byte word

Bank index = word mod 32

mod 32 wrap-around

Stride s and bank of thread i

gcd predicts conflict degree

Row-major r times C plus c

Bank conflicts in shared memory


Where these feed next

  • Banks live inside the wider 6.2.07-Shared-memory-architecture picture.
  • The same "different lanes at once" idea in global memory is 6.2.08-Memory-coalescing.
  • The column-walk conflict is the star villain of 6.3.01-Matrix-transpose-optimization.
  • How much shared memory you can afford ties into 6.2.10-Occupancy-and-resource-limits.
  • Threads acting in lockstep also underlies 6.2.11-Warp-divergence.
  • Return to the parent: the Hinglish version of the topic.

Equipment checklist

Cover the right side and answer out loud before revealing.

A thread is
one worker running the same code on its own data, identified by threadIdx.x.
A warp is
a bundle of 32 threads that execute in lockstep and fire their memory requests simultaneously.
A byte-address vs a word
a byte is one numbered slot; a 4-byte word is four bytes glued into one float/int.
Why divide a byte-address by 4
to convert it to a word-index, since banks are 4 bytes wide and only care about words.
means
the remainder after dividing by ; it wraps around like a clock, landing in .
The master bank formula
.
What stride measures
the gap in words between the elements read by thread and thread ; thread hits bank .
is
the largest whole number dividing both and ; equals the conflict degree.
Why coprime strides are safe
if the map is a permutation hitting all 32 banks.
Word address of matrix[r][c] (row-major, columns)
; a column walk has stride .
Why padding from 32 to 33 works
, so each row-step shifts by one bank instead of colliding.