같은 행렬, 두 layout, bandwidth 6× 차이
2-D 행렬이 메모리에선 사실 2-D로 안 살아 — RAM은 큰 1-D array야. 어떻게 펼치냐 선택이 어느 thread가 효율적으로 읽을 수 있는지 바꿔.
- Row-major (C order) — 주소가 row 따라 행진:
M[i][j]랑M[i][j+1]이 메모리에서 인접. C/C++, Python/NumPy, PyTorch, MLX, Metal default. - Column-major (Fortran order) — 주소가 column 따라 내려감:
M[i][j]랑M[i+1][j]이 인접. Fortran, MATLAB, R, 그리고 (BLAS가 1979년 spec 됐기 때문에) cuBLAS default.
왜 중요하냐 — GPU는 메모리를 coalesced 청크로 읽어: warp 안 32 thread가 32 contiguous 주소 요청하면 한 transaction에 가져와. 그 thread들이 non-contiguous하게 stride하면 하드웨어가 만족시키려고 transaction 여러 번 — bandwidth 폭락.
구체 숫자, RTX 4090에서 4096×4096 FP32 sum:
- Row-major, thread가 row 스캔 (coalesced): 610 GB/s
- Column-major, thread가 row 스캔 (strided): 105 GB/s
전적으로 메모리 access 패턴이 만든 6× 격차야.
Roofline: bandwidth + compute 한 천장으로 합치기
Roofline 모델 말하길: 달성 가능한 성능은
min(peak FLOPs, peak bandwidth × arithmetic intensity)로 bound.
X축에 커널 intensity, Y축에 달성 FLOP 그려; 비스듬한 bandwidth 천장 (memory-bound, 낮은 intensity) 아래거나 평평한 compute 천장 (compute-bound, 높은 intensity) 아래야. roofline knee의 어느 쪽이냐가 어떤 최적화 쫓을지 알려줘.