gpumode · 강의 아카이브
《GPU Mode · ScaleML》 L075 2025 High priority transcript · failed

GPU Programming Fundamentals + ThunderKittens

두 명의 저자가 한 강의에서 풀어낸 두 갈래 — William Brandon 의 GPU 프로그래밍 fundamentals (memory hierarchy, warp, async copy 의 원리적 정리) 와 Simran Arora 의 ThunderKittens (HazyResearch 의 tile-DSL 위에서 H100 의 855 TFLOPs 를 100 줄 안에 짜는 실증). "왜 또 다른 DSL 이 필요한가" 의 답을 모듈 단위로 깐 학습 노트.

ThunderKittens tile DSL H100 WGMMA TMA producer-consumer attention GEMM HazyResearch
W
Speaker
William Brandon
MIT · attention systems
S
Speaker
Simran Arora
Stanford · HazyResearch · ThunderKittens 공동저자
강의 번호
L075
시리즈
ScaleML
학습 우선순위
High
자막
failed
§ 01강의가 풀려는 문제· why this lecture exists

"왜 또 다른 GPU DSL 이 필요한가" 에 대한 길고 친절한 답

2024 년 시점에서 GPU 프로그래밍의 풍경은 이미 복잡하다 — CUDA, Triton, CUTLASS, cuDNN, torch.compile 의 Inductor. 그 위에 또 하나의 라이브러리(ThunderKittens) 가 왜 필요한지부터 답하지 않으면 강의는 시작될 수 없다.

강의는 두 명의 화자가 두 단계로 답을 나눈다.

  1. William Brandon — fundamentals. H100 의 메모리 계층(HBM ↔ L2 ↔ SMEM ↔ register), warp 와 warpgroup, TMA(Tensor Memory Accelerator), WGMMA(Warpgroup Matrix Multiply-Accumulate) 같은 하드웨어 사실들을 정리한다. 이 사실들이 곧 DSL 이 어떤 형태가 되어야 하는지를 결정한다.
  2. Simran Arora — ThunderKittens. 위 fundamentals 위에 얹는 mini-DSL 의 디자인 — tile 을 1급 시민으로, producer/consumer 를 명시적 abstraction 으로, 그러면서도 CUDA 처럼 직접 PTX 까지 내려갈 수 있게.
강의의 인지적 frame

"DSL 의 추상 레벨이 hardware tile 의 실제 모양과 1:1 로 맞을 때 가장 빠르고 쓰기 쉽다." Hopper 의 WGMMA 는 16×16, TMA 는 box copy 단위, async barrier 는 mbarrier — 이 모양들을 그대로 노출한 게 ThunderKittens.

"우리는 fancy compiler 트릭이 아니라 tile 단위 primitive 를 내놓는다 — hardware 가 그 모양으로 동작하기 때문에."ThunderKittens 저자 · 확인 필요
§ 02H100 위 mini DSL 의 동기· why ThunderKittens

Hopper 가 만든 새로운 자리 — async, warpgroup, large registers

A100(Ampere) 에서 H100(Hopper) 로 넘어가면서 GPU 프로그래밍 모델 자체가 변했다. async copy 가 first-class 가 되고, warpgroup (4 warp = 128 thread) 단위의 행렬곱 명령(WGMMA)이 등장했다. 기존 CUDA / Triton 의 추상은 이 변화에 자연스럽게 맞지 않는다.

FIG · H100 의 새로운 자리왜 기존 DSL 추상이 새는가
HBM3 bandwidth
3.35 TB/s
SMEM (per SM)
228 KB
register file (per SM)
256 KB
peak BF16 tensor
989 TFLOPs
peak FP8 tensor
1979 TFLOPs
SMEM 과 register 는 더 이상 "작은" 자리가 아니다 — 한 SM 에 register 만 256KB, SMEM 228KB. 이 만한 공간을 효과적으로 채우려면 tile 단위 lifetime 관리가 핵심이고, 그것이 ThunderKittens 의 출발점.

왜 기존 도구로는 부족한가 — 세 가지 구체적 부담.

§ 03tile · register · smem 추상· three core abstractions

tile 이 1급 시민이 되는 mini-algebra

ThunderKittens 의 모든 코드는 tile 위에서 돈다. 최소 단위 16×16, 자료형은 register 에 있는 rt 와 shared memory 에 있는 st. 그리고 row/column vector 는 tile 의 reduction 결과로 자연스럽게 따라온다.

FIG · ThunderKittens 의 핵심 자료형 4 가지모두 16×16 tile 의 변형
REG TILE
rt<T,M,N>
register 에 분산. warp 단위 ownership. WGMMA accumulator 의 자리.
SMEM TILE
st<T,M,N>
shared memory 에 상주. block 단위 ownership. TMA 의 destination/source.
REG VEC
rv<T,N>
tile 의 row 또는 column reduction 결과. softmax 의 max/sum 자리.
GLOBAL TILE
gl<T,…,M,N>
HBM 의 indexed view. TMA descriptor 의 wrapper.
이 네 자료형 위에서 copy, load, store, mul, mma_AB, row_max, exp, sub_row 같은 연산이 정의된다. 모두 tile 단위라서 inner loop 에서 사람이 thread index 를 들고 다닐 일이 없다.

대표 연산 몇 가지의 의미.

  • kittens::load(st, gl) — global → smem TMA copy 발사. 비동기, mbarrier 로 완료 통지.
  • kittens::mma_AB(rt_acc, rt_a, st_b) — WGMMA. accumulator 는 register, B 는 SMEM. Hopper 가 요구하는 layout 자동 처리.
  • kittens::row_max(rv, rt) — tile 의 행별 max 를 vector 로 reduction. softmax 의 첫 단계.
  • kittens::exp(rt), kittens::sub_row(rt, rv) — tile 위에서 원소별 / 행 broadcast 연산.

모든 연산이 scope hierarchy (warp / warpgroup / block) 위에서 정의되며, 같은 함수의 warpgroup 버전은 4 warp 협업으로 큰 tile 을 한 번에 처리한다.

// ThunderKittens 의 GEMM inner loop (개념)
using a_t = st<bf16,128,64>;
using b_t = st<bf16,64,128>;
using c_t = rt<float,128,128>;

c_t acc; kittens::zero(acc);

for (int k = 0; k < K; k += 64) {
  // async TMA copy
  kittens::load_async(a_smem, A.tile_at(m,k));
  kittens::load_async(b_smem, B.tile_at(k,n));
  kittens::wait(barrier, phase);

  // WGMMA on warpgroup of 4 warps
  warpgroup::mma_AB(acc, a_smem, b_smem);
  warpgroup::mma_commit_group();
}

warpgroup::mma_async_wait();
kittens::store(C.tile_at(m,n), acc);
대조 — Triton

Triton 에서 같은 일을 짜면 tl.dot 한 줄로 끝나지만, 그 한 줄이 어떻게 WGMMA 로 lowering 되는지 는 컴파일러가 결정한다. ThunderKittens 는 그 lowering 을 사람의 손에 돌려준다 — 더 긴 코드, 더 직접적인 통제.

§ 04producer-consumer 패턴· async pipeline

"warp 의 역할을 분리한다" 가 H100 시대 커널의 표준

CUDA 의 전통은 모든 thread 가 동일한 일을 한다 (SIMT). H100 시대에는 그 모델이 깨진다 — 일부 warp 는 TMA 만 발사하고, 다른 warp 는 MMA 만 돌린다. 이게 warp specialization, ThunderKittens 가 가장 잘 잡아주는 패턴.

Producer warps

1. tile load 발사 (TMA, async)
2. mbarrier::arrive 로 완료 알림
3. 다음 K iteration 의 tile 으로 이동
4. 멀티 stage buffer 를 round-robin 사용
→ 결국 SMEM 채우는 일만 한다

Consumer warps

1. mbarrier::wait — tile 도착 대기
2. WGMMA 발사 (current stage)
3. 결과 register 에 누적
4. next stage 로 이동, producer 에 release
→ MMA 만 돌린다
FIG · 멀티 stage producer-consumer timeline2-stage 예시 — actual FA3/FA4 는 더 복잡
producer load tile 0 load tile 1 load tile 2 load tile 3 load tile 4 consumer mma tile 0 mma tile 1 mma tile 2 mma tile 3 SMEM stage stage 0 fill stage 1 fill / 0 use stage 0 reuse stage 1 reuse → producer 는 MMA latency 를 가린다 (tile 1 을 미리 로드해 둠)
core idea: producer 의 load 와 consumer 의 mma 가 시간상 겹친다. SMEM 의 stage buffer 가 그 겹침을 가능하게 한다. 단계 수 (stage) 는 보통 2-4. ThunderKittens 의 template 이 stage 갯수를 parameter 로 받는다.
§ 05예제: attention· FlashAttention-3 in TK

FA3 의 ping-pong 을 ThunderKittens 의 추상으로 다시 짜기

강의에서 가장 진하게 다뤄진 예제. FlashAttention-3 의 핵심 트릭(warpgroup 두 그룹이 ping-pong 으로 softmax 와 MMA 를 번갈아 돌린다)을 ThunderKittens 의 producer/consumer 추상으로 풀어 본다.

FA3 가 H100 에서 잘 도는 이유는 두 가지.

  1. QK^T MMA 와 softmax 의 register 의존 — softmax 는 row-wise reduction 이라 register tile 안에 leftover dependency 가 생긴다. 두 warpgroup 이 번갈아 돌면 그 dependency 가 직렬화되지 않는다.
  2. Output PV MMA 의 별도 stream — softmax 결과 P 를 다시 V 와 곱해 O 를 만든다. 이걸 같은 warpgroup 이 하면 ping-pong 이 다시 막힌다.
ThunderKittens 가 자연스럽게 잡는 부분

warpgroup::<G0>warpgroup::<G1> 의 명시적 분리, 그리고 stage buffer 의 round-robin. ping-pong 패턴을 코드 구조로 표현하므로 컴파일러의 의도 추론이 필요 없다.

// ThunderKittens FA3-style attention (개념)
template<int NUM_WORKERS>
__global__ void attn_kernel(...) {
  if (warpid < 2) {
    // PRODUCER warps
    for (int k=0; k<Tk; ++k) {
      tma::load_async(K_smem[stage], K_gmem[k]);
      tma::load_async(V_smem[stage], V_gmem[k]);
      tma::arrive(barrier[stage]);
      stage = (stage+1) % STAGES;
    }
  } else {
    // CONSUMER warpgroups (G0 / G1 ping-pong)
    for (int k=0; k<Tk; ++k) {
      tma::wait(barrier[stage], phase);
      warpgroup::mma_AB(s_acc, q_reg, K_smem[stage]);
      warpgroup::mma_commit_group();
      // softmax on the OTHER group while this one mma's
      if (group_id == 0) other.softmax_async();
      warpgroup::mma_async_wait();
      kittens::row_max(m_new, s_acc);
      kittens::exp(s_acc);
      // online softmax accumulator update ...
    }
  }
}

실제 ThunderKittens repo 의 examples/attn/h100/ 안에 FA3 와 호환되는 reference 구현이 있고 — 강의에서는 그 코드의 핵심 30 여 줄이 어떻게 FA3 의 trick 들을 그대로 노출하는지 line-by-line 로 짚는다 (확인 필요).

"Triton 으로 FA3 를 짤 수 없는 게 아니다 — 다만 ping-pong 의 의도를 코드 구조에서 보고 싶다면 ThunderKittens 가 더 가까운 표현이다."학습 노트
§ 06예제: GEMM· 855 TFLOPs in 100 lines

"H100 peak 의 86% 를 100 줄 안에" — 의 진짜 의미

ThunderKittens 의 가장 자주 인용되는 숫자 — H100 위 BF16 GEMM 에서 855 TFLOPs (peak 989 의 86%) 를 100 줄 미만 코드로. 비교 기준을 어떻게 잡느냐에 따라 의미가 달라진다.

TAB · GEMM 구현 비교H100 SXM · BF16 · 4096³ · 개념적
구현코드 길이TFLOPspeak%특징
cuBLAS(closed source)~900~91%NVIDIA 의 hand-tuned. arch 별 변형.
CUTLASS 3~수천 줄 template~880~89%full-feature, all dtypes, but 진입 장벽 높음
Triton~80 줄~750-800~76-81%autotuner 없으면 더 낮음. 매우 짧음.
ThunderKittens<100 줄~855~86%tile primitive 직접. WGMMA explicit.
raw CUDA + WMMA~수백 줄~880~89%가장 빠르지만 가장 어려움
"86% 를 100 줄 안에" 의 의미는 단순히 빠른 게 아니다 — 그 속도를 사람이 코드를 읽고 이해할 수 있는 형태로 얻었다는 것. CUTLASS 의 코드는 빠르지만 학습 자료로는 거의 사용 불가능하다.

왜 ThunderKittens 가 86% 를 받는지 두 가지 핵심.

§ 07Triton 과 비교· where TK fits

"같은 산을 다른 길로 오른다" — 두 도구의 위치

ThunderKittens 는 Triton 의 대체재가 아니라 다른 추상 레벨의 도구다. 강의에서 두 저자가 명시적으로 짚은 비교.

TAB · ThunderKittens vs Tritonwhere each shines
차원TritonThunderKittens
언어Python DSL, jitC++ template + CUDA
tile 정의tl.arange + indexingrt<T,M,N> first-class type
WGMMAcompiler 가 tl.dot 에서 lowering사람이 warpgroup::mma_AB 직접
TMA / async대부분 자동, 통제 제한explicit TMA descriptor + mbarrier
autotuningTriton 의 강점, BLOCK_SIZE sweep없음 — template parameter 직접
학습 곡선완만, Python 만 알면 시작가파름, CUDA + Hopper 모델 이해 필요
최적 use case새 op 빨리 짜기, fusion experimentFA / GEMM 같은 경계까지 짜내기
portabilityNV / AMD 모두H100 (TK), B200 (TK4), AMD (HipKittens), Apple (ThunderMittens) 분기
언제 어떤 걸 쓰는가

새 attention variant 를 빠르게 prototype → Triton. peak 에 가까운 production kernel → ThunderKittens. 두 단계의 워크플로가 자연스럽다 — 먼저 Triton 으로 정확성 확인, 핫패스만 TK 로 다시 짠다.

"ThunderKittens 는 fancy 한 게 아니라 단순한 거다 — hardware 가 tile 단위로 동작하니 DSL 도 tile 단위로 짠다."Simran Arora · 확인 필요
§ 08채택 사례· production users

research toy 가 아니다 — 산업 코드베이스 안에 들어가 있다

채택의 공통 패턴 — 모두 "기존 cuBLAS / FlashAttention 으로는 풀기 어려운 한 자리" 가 있는 곳. 새 attention variant, 비표준 GEMM shape, 또는 fused custom operator.

채택 곡선의 분기점

ThunderKittens 가 "또 다른 DSL" 에서 "쓸만한 도구" 로 넘어간 시점은 H100 의 폭넓은 가용성이 만들어진 2024 중반. 그 전까지는 A100 의 CUTLASS 가 dominant 했고, ThunderKittens 의 추상 가치는 Hopper 의 새 기능들 (TMA, WGMMA, async warpgroup) 위에서만 진하게 드러났다.

§ 09다음 방향· HipKittens · ThunderMittens

"같은 추상, 다른 하드웨어" 로의 확장

큰 그림 — tile-first DSL 이 단일 회사의 single-arch 도구가 아니라 크로스 아키텍처 추상 으로 자리잡으려는 시도. 성공 여부는 AMD/Apple 위 성능과 채택 곡선이 결정.

§ 10기억할 메모· key takeaways

다시 열었을 때 손에 잡혀야 할 것

tile = first-class
코드 안에서 thread 가 아니라 16×16 tile 이 계산의 단위. ownership 은 warp / warpgroup / block.
rt vs st
register tile vs SMEM tile. WGMMA 의 accumulator 는 항상 rt, B 행렬은 st.
producer / consumer
warp 가 같은 일 안 한다. async TMA 는 producer 가, WGMMA 는 consumer 가. mbarrier 로 동기.
stage buffer
producer 가 채우고 consumer 가 비우는 SMEM 의 round-robin. 보통 2-4 stage. parameter 로 노출.
855 TFLOPs / 100 lines
H100 peak 의 86% 를 사람이 읽을 수 있는 코드로. CUTLASS 의 wall 을 부수는 가치.
vs Triton
대체재가 아닌 다른 레벨. prototype 은 Triton, 핫패스는 TK 의 두 단계 워크플로.
cross-arch 분기
HipKittens (AMD), ThunderMittens (Apple). 같은 추상의 다른 하드웨어 매핑.
FA3 / FA4 reference
attention 의 ping-pong / 5-way specialization 이 TK 코드 안에 자연스럽게 떨어짐.

손에 새기기 — 실습 시퀀스

  1. TK 의 hello-world GEMM — 256³ BF16 matmul 을 TK 로 짠다. warpgroup::mma_AB 한 줄이 어떤 PTX 로 lowering 되는지 ncu 의 SASS view 로 확인.
  2. 2-stage producer/consumer — TK 의 stage buffer 갯수를 1, 2, 3, 4 로 바꿔가며 GEMM 의 throughput 을 측정. stage=2 부근에서 plateau 가 보이는지 확인.
  3. WGMMA layout 학습 — accumulator register tile 의 element 가 어떤 thread/warp 에 분산되는지 직접 print 해본다. swizzling 의 그림이 손에 잡힐 때까지.
  4. TMA 의 box copy 직접 발사 — descriptor 만 만들어서 cp.async.bulk.tensor 한 번 발사. mbarrier::wait 로 완료 확인. async copy 의 model 을 손에 익힌다.
  5. FA3 의 ping-pong 패턴 직접 짜기 — TK 의 examples/attn 을 copy 해서 한 줄씩 분해. 두 warpgroup 이 어떻게 번갈아 도는지 print debug 로 직접 본다.
  6. Triton 과의 동일 op 비교 — 같은 GEMM shape 을 Triton 과 TK 로 짜고 throughput / SASS / register usage 를 직접 diff.
§ 11다른 강의로의 연결· connections

이 강의가 시리즈 안에서 어디로 이어지는가

§ 12열린 질문· open questions

다음에 다시 들었을 때 직접 검증해야 할 것들

검증 메모

이 노트는 ThunderKittens 공식 repo / blog post / 도메인 지식으로 재구성. 자막이 없어 두 화자의 발화 순서, 시연 코드의 정확한 라인 수 등은 영상 직접 확인 필요. 특히 § 06 의 비교표 수치는 추정값으로 — 직접 GEMM 을 돌려 확인 권장.

← Lecture 074Positional Encodings & PaTH Attention Lecture 076 →BackendBench — fixing LLM kernel correctness