Intuition The one core idea
Shared memory is split into 32 parallel lanes called banks , and all 32 threads of a warp can read at once only if each thread lands in a different bank . Everything in this topic is one question repeated: "given how my threads index the array, do any two of them land in the same bank?"
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.
A thread is one worker running your program. On a GPU you launch thousands of them, and they all run the same line of code but on different data — thread number 5 handles element 5, thread number 6 handles element 6, and so on.
The number that tells a thread "who am I" is written threadIdx.x. If you have 32 threads, threadIdx.x runs 0 , 1 , 2 , … , 31 . We will call this number i throughout.
A warp is a fixed bundle of 32 threads that the hardware runs in lockstep — they all execute the same instruction at the same instant. When those 32 threads hit a shared-memory read, all 32 memory requests are fired simultaneously . That simultaneity is the whole reason banks matter.
Intuition Why 32 keeps appearing
There are 32 threads in a warp and 32 banks in shared memory. This is not a coincidence — the hardware is built so that a perfectly-behaved warp maps its 32 threads onto its 32 banks one-to-one. Every "conflict" is a failure of that one-to-one match.
Definition Byte and byte-address
A byte is 8 bits — the smallest chunk of memory that has its own numbered slot. That number is the byte-address : byte 0, byte 1, byte 2, … Think of memory as an infinitely long ruler where every millimetre is numbered.
Definition Word (a 4-byte word)
A float (and an int) takes 4 bytes . Four consecutive bytes glued together and treated as one value is called a 32-bit word (32 bits = 4 bytes). So byte-addresses 0 , 1 , 2 , 3 are all inside word 0 ; bytes 4 , 5 , 6 , 7 are word 1 ; and so on.
To turn a byte-address into a word-number you divide by 4 and throw away the remainder:
word_index = ⌊ 4 byte_address ⌋
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.
Intuition Why bother with words at all?
The banks are 4 bytes wide, so the bank hardware doesn't care about individual bytes — it only cares which 4-byte word you asked for. Converting to word-index first is the step that lets the next formula ignore the messy byte details.
Definition Modulo, written
mod or mod
a mod n means "the remainder left over after you divide a by n ." Example: 7 mod 3 = 1 because 7 = 2 × 3 + 1 . It always lands somewhere in 0 , 1 , … , n − 1 .
The picture is a clock face . A clock does mod 12 : after 12 you wrap back to 0. Bank assignment does mod 32 : after word 31 you wrap back to bank 0.
mod 32 and not something else?
With only 32 physical banks, word number 32 has nowhere new to go — the round-robin must wrap. mod 32 is exactly the arithmetic of "keep dealing cards into 32 piles, one card per pile, starting over at pile 0 each lap." Any tool that captures wrap-around would do; mod is the standard name for it.
s
Stride is the gap, measured in words , between the element thread i reads and the element thread i + 1 reads. In shared[i] the gap is 1 word (stride 1). In shared[i*2] the gap is 2 words (stride 2). In matrix[i][col] with 32 columns, moving one row jumps 32 words (stride 32).
So thread i reads word i ⋅ s , and therefore lands in bank
bank ( i ) = ( i ⋅ s ) mod 32.
This single line is the engine of the whole topic. Everything the parent note computes is this line with a specific s plugged in.
Worked example Feel the stride
Stride 1: banks are 0 , 1 , 2 , … , 31 — all different, one-to-one , no conflict.
Stride 2: banks are 0 , 2 , 4 , … , 30 , 0 , 2 , … — bank 0 is hit by thread 0 and thread 16. Collision.
Stride 32: every thread's bank is ( i ⋅ 32 ) mod 32 = 0 — all 32 pile onto bank 0.
Definition Greatest common divisor,
g cd( a , b )
g cd( a , b ) is the biggest whole number that divides both a and b evenly. g cd( 2 , 32 ) = 2 , g cd( 3 , 32 ) = 1 , g cd( 16 , 32 ) = 16 . When g cd( s , 32 ) = 1 we say s and 32 are coprime (they share no factor but 1).
right tool
We want the smallest step k such that two threads k apart land in the same bank, i.e. ( k ⋅ s ) mod 32 = 0 . That is asking "when does k ⋅ s first become a multiple of 32?" — a pure question about shared factors between s and 32 . The mathematical name for shared-factors reasoning is the gcd. No other tool answers "how soon do we wrap exactly onto a used bank" as cleanly.
The payoff formula the parent uses:
conflict_degree = g cd( s , 32 )
Coprime stride (g cd= 1 ): the map i ↦ ( i ⋅ s ) mod 32 hits all 32 banks — a permutation, perfectly conflict-free. (This is why the odd-stride .x field access is safe.)
g cd= d > 1 : only 32/ d distinct banks are used, so d threads share each one — a d -way conflict.
Definition Row-major layout
A 2-D array matrix[R][C] is really a 1-D strip in memory. Row-major means row 0 is laid out first, then row 1, etc. Element [r][c] sits at word:
word = r ⋅ C + c
where C is the number of columns. Moving one column (c → c + 1 ) steps 1 word; moving one row (r → r + 1 ) steps C words.
That is why reading a column (matrix[i][col], varying the row i ) has stride C : it is the worst case when C = 32 , and it becomes safe when you pad to C = 33 (because 33 mod 32 = 1 , turning the row-step back into a friendly stride of 1 in bank-space ).
Stride s and bank of thread i
gcd predicts conflict degree
Row-major r times C plus c
Bank conflicts in shared memory
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 .
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.
a mod n meansthe remainder after dividing a by n ; it wraps around like a clock, landing in 0 … n − 1 .
The master bank formula bank_index = word_index mod 32 .
What stride s measures the gap in words between the elements read by thread i and thread i + 1 ; thread i hits bank ( i ⋅ s ) mod 32 .
g cd( a , b ) isthe largest whole number dividing both a and b ; g cd( s , 32 ) equals the conflict degree.
Why coprime strides are safe if g cd( s , 32 ) = 1 the map i ↦ ( i ⋅ s ) mod 32 is a permutation hitting all 32 banks.
Word address of matrix[r][c] (row-major, C columns) r ⋅ C + c ; a column walk has stride C .
Why padding C from 32 to 33 works 33 mod 32 = 1 , so each row-step shifts by one bank instead of colliding.