As asked
Walk me through how global memory coalescing works in CUDA. If a kernel is reading a 2D matrix column-by-column, what happens at the hardware level and how would you fix it?
Sample answer outline
A strong answer explains that CUDA groups 32 threads into a warp and that the GPU serves a single 128-byte cache line per memory transaction per warp. Reading column-by-column means each thread in the warp accesses a non-contiguous address, causing 32 separate transactions instead of one and wasting bandwidth by a factor of up to 32x. The fix is typically to transpose the access pattern, store the matrix in column-major order, or use shared memory as a staging buffer to re-order the reads. The candidate should mention that modern Ampere and Hopper GPUs have better L2 caches but coalescing still matters at scale.
Reference implementation (cuda)
__global__ void colReadKernel(float* mat, float* out, int rows, int cols) {
int tid = blockIdx.x * blockDim.x + threadIdx.x;
// Bad: threads in a warp read from different rows (stride = cols)
if (tid < cols)
out[tid] = mat[tid]; // warp reads mat[0], mat[cols], mat[2*cols]...
}
// Fix: transpose first or use shared memory tilingExpect these follow-ups
- How does shared memory help here and what is its latency relative to global memory?
- How would you profile this bottleneck using Nsight Compute?