자막
음성

Lec 29 · GPU Architecture (2): shared memory tiling, bank conflict, coalescing

정밀 정리 · 검증 2026-09-24 10:50

1개요

1.1shared memory 를 이용한 tiling 공통 전략과 DRAM 접근 감소 원리
1.2matrix multiply: naive kernel → tiled kernel(__syncthreads), GT200 에서 17.2x
1.3Volta shared memory 32 banks 구조, bank conflict 판정 예제
1.4matrix transpose: naive → coalesced(shared tile) → padding 으로 bank conflict 제거, DRAM burst·coalescing 설명

2섹션별 정리 상황·문제 → 원인 → 해결

2.10:22–4:07Recap: GPU memory hierarchy 와 cache vs shared memory
상황·문제지난 강의 복습: global·local memory 는 DRAM, register 는 on-chip register file, shared memory 는 block 내 공유 on-chip memory
원인cache 는 HW-managed 라 프로그램 의도를 몰라 공간 낭비·implicit data movement 발생
해결shared memory 는 SW-managed, hit/miss 없는 deterministic 접근; 대신 data 이동을 programmer 가 명시
  • block 은 다른 block 의 shared memory 를 볼 수 없음
  • 여러 thread 가 자주 쓰는 data 를 shared memory 에 두어 성능 최적화
p.30
2.1.1 · p.30 · 1:11
p.31
2.1.2 · p.31 · 2:43
2.1.r.1Wikipedia: Scratchpad memory ↗ · software-managed on-chip memory, CUDA shared memory 가 scratchpad 임을 명시
2.24:07–7:48shared memory tiling 공통 전략
상황·문제input 전체는 shared memory(CPU 는 cache)에 들어가지 않음
원인DRAM 접근을 thread 몇 개로만 하면 개별 thread 성능이 낮아 bottleneck
해결data 를 tile 로 partition, tile 하나를 thread block 하나가 담당: 여러 thread 로 global→shared load(memory-level parallelism) → shared 에서 계산(multi-pass 가능) → 결과를 global 로 copy
  • CPU 에서도 쓰는 일반 기법(tiling/blocking)
  • 결과는 다른 kernel 이 쓰거나 host 로 copy
p.36
2.2.1 · p.36 · 4:07
p.41
2.2.2 · p.41 · 7:35
2.2.r.1Wikipedia: Loop nest optimization (loop tiling) ↗ · cache/on-chip 에 맞게 iteration space 를 tile 로 나누는 일반 기법, matrix multiply 예
2.2.r.2NVIDIA CUDA C++ Best Practices Guide ↗ · 10.2.1 Coalesced Access, 10.2.3.1 Shared Memory and Memory Banks, 10.2.3.2 Shared Memory in Matrix Multiplication
2.37:48–9:29shared memory blocking 의 DRAM 접근 감소 효과
상황·문제shared memory 없이 모든 thread 가 모든 data 를 global memory 에서 반복 접근
원인DRAM 접근 수 = 원소 수 x thread 수
해결tile 을 shared memory 에 한 번 올리고 여러 thread 가 공유 → DRAM 접근 수가 data 크기에 비례
  • tile 단위로 load → 공유 접근 → 다음 tile
p.42
2.3.1 · p.42 · 7:48
2.49:29–16:23matrix multiplication: host 코드와 naive CUDA kernel
상황·문제P = M x N 을 GPU 로 매핑: thread 하나가 output 원소 하나, block 은 TILE_WIDTH^2 sub-matrix(예 4x4 에 TILE_WIDTH=2 → 4 blocks x 4 threads)
원인naive kernel 은 각 thread 가 M 의 row·N 의 column 을 global memory 에서 직접 읽음 → 같은 column 이 block 내 2번, 전체 4번 load
해결2D 배열은 동적 할당이라 1D index 로 flatten; 이 중복 load 를 shared memory 로 줄이는 것이 다음 단계
  • Row = blockIdx.y*blockDim.y+threadIdx.y, Col = blockIdx.x*blockDim.x+threadIdx.x
  • grid 가 matrix 보다 클 수 있어 범위 check
  • 슬라이드 코드에 문자 하나 빠짐(강의 중 지적)
p.43
2.4.1 · p.43 · 9:29
p.44
2.4.2 · p.44 · 10:54
p.47
2.4.3 · p.47 · 13:30
2.516:23–24:50tiled matrix multiply with shared memory
상황·문제한정된 on-chip memory 로 matrix multiply 의 global memory 접근을 줄여야 함
원인thread 들이 서로 다른 속도로 진행하므로 load 완료 전 계산하면 틀림
해결phase 마다 block 의 모든 thread 가 M·N 원소 1개씩 shared tile 로 load → __syncthreads() → 부분곱 누적 → __syncthreads() → 다음 tile; 마지막에 Pvalue 를 global 에 write
  • load 는 warp 내 coalesced 되도록 배정
  • tile m index: M[Row*Width + m*TILE_WIDTH + tx], N[(m*TILE_WIDTH+ty)*Width + Col]
  • shared 배열은 compile-time 크기라 2D index 사용 가능
p.48
2.5.1 · p.48 · 16:37
p.52
2.5.2 · p.52 · 19:11
p.60
2.5.3 · p.60 · 23:42
2.5.r.1NVIDIA CUDA C++ Best Practices Guide ↗ · 10.2.1 Coalesced Access, 10.2.3.1 Shared Memory and Memory Banks, 10.2.3.2 Shared Memory in Matrix Multiplication
2.624:50–28:21tiling 의 global load 감소와 GT200 성능
상황·문제naive 는 global load 2N^3
원인각 tile 은 여전히 여러 block 이 반복 load 하지만 횟수가 N/TILE_WIDTH 로 줄어듦
해결global load 2N^2*(N/TILE_WIDTH): TILE_WIDTH=32 면 1/32; GT200 에서 10.7 → 183.9 GFLOPS(17.2x), SLOC 증가 대비 7.8x
  • 강의에서는 '약 18배'라고 말함(슬라이드 17.2x)
p.61
2.6.1 · p.61 · 24:50
2.728:21–33:28Volta shared memory 구조와 bank
상황·문제더 많은 최적화를 위해 shared memory 의 조직을 알아야 함
원인shared memory 는 32 banks x 4B, 연속 4B word 가 연속 bank 에 mapping
해결bank 당 4B/clock → 128B/clock/SM, V100 80 SM 합계 ~14 TB/s (DRAM 1 TB/s 미만 대비 14배 이상)
  • bank = (4B word index) % 32, 1B 접근은 /4 후 %32
  • 8B data 는 두 bank 에 걸침(강의에서 '4-byte 는 두 번 접근'이라 말한 것은 8-byte 의 오기)
  • 기본 48KB/threadblock, opt-in 96KB
p.63
2.7.1 · p.63 · 28:31
p.64
2.7.2 · p.64 · 32:31
2.7.r.1NVIDIA Tesla V100 GPU Architecture whitepaper (2017) ↗ · GV100 shared memory 최대 96 KB/SM, HBM2 900 GB/s (PDF 텍스트 확인)
2.833:28–40:16bank conflict 와 access pattern 예제
상황·문제warp 의 shared memory load 는 lock-step 으로 한 instruction
원인2개 이상 thread 가 같은 bank 의 다른 word 를 접근하면 N-way bank conflict → replay(32-way 면 31번)
해결같은 word 접근(broadcast)이나 같은 word 의 다른 byte 는 conflict 아님; 프로그램에서 bank conflict 최소화
  • 66~69쪽: 모두 다른 bank 이거나 같은 word → conflict 없음
  • 70~71쪽: 2-way, 72쪽: 3-way (T-0,T-1,T-2 가 bank 1)
p.65
2.8.1 · p.65 · 33:30
p.69
2.8.2 · p.69 · 38:32
p.72
2.8.3 · p.72 · 40:00
2.8.r.1NVIDIA blog: Using Shared Memory in CUDA C/C++ ↗ · shared memory 할당, __syncthreads(), 32 banks bank conflict 설명
2.8.r.2NVIDIA CUDA C++ Best Practices Guide ↗ · 10.2.1 Coalesced Access, 10.2.3.1 Shared Memory and Memory Banks, 10.2.3.2 Shared Memory in Matrix Multiplication
2.940:16–49:35matrix transpose naive kernel 과 32x8 block
상황·문제1024x1024 transpose 를 32x32 tile, 32x8 thread block 으로 구현(j loop 4회)
원인본 연산이 load 하나·store 하나뿐이라 thread index 계산 overhead 가 본 연산과 비슷한 크기
해결block 을 줄이고 loop 로 thread 당 4원소 처리 → index 계산 overhead 를 amortize
  • naive 부터 짜고 최적화마다 성능 측정 권장
  • 학생 답(bank conflict, int 크기)은 오답: 아직 shared memory 를 안 씀
p.73
2.9.1 · p.73 · 40:16
2.9.r.1NVIDIA blog: An Efficient Matrix Transpose in CUDA C/C++ ↗ · 73~80쪽 원출처: transposeNaive/Coalesced/NoBankConflicts, TILE_DIM+1 padding, M2050·K20c 표
2.1049:35–56:40DRAM burst 와 memory coalescing
상황·문제DRAM 은 command overhead 를 amortize 하려 burst 단위로 전송(DDR 로 한 command 에 2 burst 이상)
원인GDDR 은 burst length 8 x 32-bit = 32B chunk 가 최소 단위; chunk 일부만 쓰면 bandwidth 낭비
해결warp 의 인접 thread 가 같은 burst section 을 접근하도록 → DRAM command 최소화; strided 접근은 uncoalesced
  • 32 threads x 4B = 128B → 32B chunk 4개(강의 중 16B/32B 혼동 후 정정)
  • load 뿐 아니라 write 도 coalescing 필요
p.74
2.10.1 · p.74 · 49:35
p.75
2.10.2 · p.75 · 52:23
p.76
2.10.3 · p.76 · 54:58
2.10.r.1NVIDIA blog: How to Access Global Memory Efficiently in CUDA C/C++ Kernels ↗ · warp 단위 coalescing, misaligned·strided access 의 bandwidth 영향 실측
2.10.r.2Wikipedia: Burst mode (computing) ↗ · DRAM burst 전송 개념(초기 latency 후 연속 전송)
2.1156:40–1:02:04shared memory 로 coalesced transpose
상황·문제naive 는 write 가 uncoalesced
원인nearby thread 가 서로 다른 x 를 가져 output 에 stride 접근
해결tile 을 coalesced 로 shared 에 load → __syncthreads() → block offset(x,y) 교환 후 tile 에서 column 을 읽어 coalesced write
  • shared tile 은 2D index, 동적 할당 input 은 1D flatten
  • idata = input, odata = transposed output (학생 질문)
p.77
2.11.1 · p.77 · 56:22
2.11.r.1NVIDIA blog: An Efficient Matrix Transpose in CUDA C/C++ ↗ · 73~80쪽 원출처: transposeNaive/Coalesced/NoBankConflicts, TILE_DIM+1 padding, M2050·K20c 표
2.121:02:04–1:06:58transpose 의 bank conflict 와 padding
상황·문제tile[32][32] 에서 warp 가 column 을 읽음
원인같은 column 원소가 모두 같은 bank → 32-way conflict, 31 replays
해결tile[TILE_DIM][TILE_DIM+1] 로 한 칸 padding → column 원소가 서로 다른 bank, row·column 모두 conflict 없음
  • padding column 은 쓰지 않는 garbage
  • 코드 변경은 '+1' 하나
p.78
2.12.1 · p.78 · 1:01:58
p.79
2.12.2 · p.79 · 1:03:34
2.12.r.1NVIDIA blog: An Efficient Matrix Transpose in CUDA C/C++ ↗ · 73~80쪽 원출처: transposeNaive/Coalesced/NoBankConflicts, TILE_DIM+1 padding, M2050·K20c 표
2.131:06:58–1:12:10성능 비교와 shared memory 요약
상황·문제최적화 단계별 효과 확인
원인Coalesced: 18.8→51.3(M2050), 55.3→97.6(K20c); NoBankConflicts: 99.5 / 144.3 GB/s
해결shared memory 는 고대역·저지연·programmer-managed; bank conflict 는 profiling tool 로 찾아 제거
  • 강의 구두 '22배(K20c)' 는 표와 불일치(실제 ~1.8x)
  • CUDA compiler 는 보통 shared memory 최적화를 자동으로 하지 않음
p.80
2.13.1 · p.80 · 1:07:25
p.81
2.13.2 · p.81 · 1:10:36
2.13.r.1NVIDIA blog: An Efficient Matrix Transpose in CUDA C/C++ ↗ · 73~80쪽 원출처: transposeNaive/Coalesced/NoBankConflicts, TILE_DIM+1 padding, M2050·K20c 표
2.13.r.2NVIDIA CUDA C++ Best Practices Guide ↗ · 10.2.1 Coalesced Access, 10.2.3.1 Shared Memory and Memory Banks, 10.2.3.2 Shared Memory in Matrix Multiplication

3핵심 개념

3.1tiling(타일링)
data 를 shared memory 에 맞는 tile 로 나눠 block 하나가 load·계산·write-back
3.1.r.1Wikipedia: Loop nest optimization (loop tiling) ↗ · cache/on-chip 에 맞게 iteration space 를 tile 로 나누는 일반 기법, matrix multiply 예
3.2barrier synchronization(__syncthreads)
block 내 모든 thread 가 도달할 때까지 대기; tile load 후·계산 후 두 번 사용
3.2.r.1NVIDIA blog: Using Shared Memory in CUDA C/C++ ↗ · shared memory 할당, __syncthreads(), 32 banks bank conflict 설명
3.3shared memory bank(뱅크)
32 banks x 4B, 연속 4B word 가 연속 bank; bank 당 4B/clock
3.3.r.1NVIDIA blog: Using Shared Memory in CUDA C/C++ ↗ · shared memory 할당, __syncthreads(), 32 banks bank conflict 설명
3.4bank conflict(뱅크 충돌)
warp 내 여러 thread 가 같은 bank 의 다른 word 접근 → N-way replay; 같은 word 는 broadcast
3.4.r.1NVIDIA CUDA C++ Best Practices Guide ↗ · 10.2.1 Coalesced Access, 10.2.3.1 Shared Memory and Memory Banks, 10.2.3.2 Shared Memory in Matrix Multiplication
3.5DRAM burst(버스트)
한 command 로 연속 chunk 전송; GDDR5 burst length 8 x 32-bit = 32B
3.5.r.1Wikipedia: Burst mode (computing) ↗ · DRAM burst 전송 개념(초기 latency 후 연속 전송)
3.6memory coalescing(메모리 병합)
warp 의 접근이 같은 burst section 에 모이면 DRAM request 1개
3.6.r.1NVIDIA blog: How to Access Global Memory Efficiently in CUDA C/C++ Kernels ↗ · warp 단위 coalescing, misaligned·strided access 의 bandwidth 영향 실측
3.7padding(패딩)
tile[32][33] 처럼 한 칸 추가해 column 접근의 bank 를 어긋나게 함
3.7.r.1NVIDIA blog: An Efficient Matrix Transpose in CUDA C/C++ ↗ · 73~80쪽 원출처: transposeNaive/Coalesced/NoBankConflicts, TILE_DIM+1 padding, M2050·K20c 표

4스스로 확인

4.1tiled matrix multiply 에서 __syncthreads() 가 두 번 필요한 이유는?
답
load 완료 전 계산 방지, 계산 완료 전 다음 tile 로 덮어쓰기 방지
4.2TILE_WIDTH=32 일 때 global load 는 naive 대비 얼마로 줄어드나?
답
2N^3 → 2N^2*(N/32), 즉 1/32
4.3T-0 이 word 1, T-1 이 word 33 을 읽으면?
답
둘 다 bank 1 의 다른 word → 2-way bank conflict
4.4transposeNaive 에서 32x32 대신 32x8 block 을 쓰는 이유는?
답
본 연산이 load/store 뿐이라 index 계산 overhead 를 loop 로 amortize
4.5tile[32][33] padding 이 column 접근 conflict 를 없애는 원리는?
답
row 마다 bank 가 1씩 밀려 column 32원소가 32개 bank 에 분산

5참고 자료

5.1NVIDIA CUDA C++ Best Practices Guide ↗ · 10.2.1 Coalesced Access, 10.2.3.1 Shared Memory and Memory Banks, 10.2.3.2 Shared Memory in Matrix Multiplication
5.2NVIDIA blog: Using Shared Memory in CUDA C/C++ ↗ · shared memory 할당, __syncthreads(), 32 banks bank conflict 설명
5.3NVIDIA blog: How to Access Global Memory Efficiently in CUDA C/C++ Kernels ↗ · warp 단위 coalescing, misaligned·strided access 의 bandwidth 영향 실측
5.4NVIDIA blog: An Efficient Matrix Transpose in CUDA C/C++ ↗ · 73~80쪽 원출처: transposeNaive/Coalesced/NoBankConflicts, TILE_DIM+1 padding, M2050·K20c 표
5.5NVIDIA Tesla V100 GPU Architecture whitepaper (2017) ↗ · GV100 shared memory 최대 96 KB/SM, HBM2 900 GB/s (PDF 텍스트 확인)
5.6Wikipedia: Loop nest optimization (loop tiling) ↗ · cache/on-chip 에 맞게 iteration space 를 tile 로 나누는 일반 기법, matrix multiply 예
5.7Wikipedia: Burst mode (computing) ↗ · DRAM burst 전송 개념(초기 latency 후 연속 전송)
5.8Wikipedia: Scratchpad memory ↗ · software-managed on-chip memory, CUDA shared memory 가 scratchpad 임을 명시
5.9Hennessy & Patterson, Computer Architecture: A Quantitative Approach 6th ed. (Elsevier) ↗ · Ch.4 Data-Level Parallelism in Vector, SIMD, and GPU Architectures (82쪽 추천 4.4-4.9)

7한국어판 강의자료

단축키
Ctrl K · s자료 검색
[ ]이전·다음 강의
Space영상 재생·정지
j k다음·이전 section
n p다음·이전 slide
b강의 목록 접기·펴기
t맨 위
/강의 검색
Esc닫기