Production에서 진짜로 바늘 움직이는 knob
| Knob | 할 일 | 이유 |
|---|---|---|
| Datatype | FP16 / BF16 weight 선호; stability 요구할 때만 FP32 누적 유지 | Matrix unit / Tensor Core path hit |
| Hidden size | 64 또는 128로 round | 128×128 block tile 완벽 채움; padding-fallback 회피 |
| 메모리 placement | Weight → private; activation → CPU read 필요할 때만 shared | Hot 데이터를 on-chip SRAM에 유지 |
| Warm-up pass | Weight load 후 dummy inference 한 번 | 라이브러리의 best algorithm 선택 캐시 |
| Batch size | Inference엔 메모리 허용하는 한 높게 | GEMV → GEMM, bandwidth-bound → compute-bound |
| Algorithm caching | cuBLASLt / autotune 선택을 run 가로질러 persist | 1–10s cold-start algo 검색 스킵 |
흔한 face-plant + 빠른 fix
| 증상 | 가능한 원인 | Fix |
|---|---|---|
| GEMM < 40% F32 utilization | Hidden size가 16 배수 아님 | M 또는 K를 64 / 128로 padding |
| Throughput 하룻밤에 절반 | 라이브러리 업그레이드 후 reduced-precision flag 켜는 걸 잊음 | 다시 켬, rebuild, flag 문서화 |
| Command buffer 사이 큰 gap | CPU tokenizer나 I/O가 queue stall | Async pre-tokenize; queue에 작업 충분히 유지 |
| 라이브러리가 silent하게 GEMV path로 swap | 작은 m이나 k (예: single-token decode 위해 head_dim = 32) | Head fuse 또는 KV-cache 다시 써서 batch ≥ 8 유지 |
| Inference latency가 5× 변동 | 라이브러리가 shape별로 heuristic 다시 돌림 | Algorithm 선택 캐시; shape별로 request 정렬 |
결론
GEMM이 transformer 수학의 90%. 라이브러리에 사랑하는 shape 먹여 (padded, batched, reduced-precision, hidden-size가 옳은 tile 경계), 뭔가 느려지면 utilization counter 슬쩍 봐, BLAS가 무거운 일 하게 둬. 손코딩 커널은 학습용 (이 quest!) 이랑 라이브러리가 진짜로 잘 안 다루는 shape용이지 default 아냐.