본문 바로가기
C.W.K.
Lesson 02 of 06 · published

NVIDIA가 앞서는 곳: 대역폭과 날것의 연산

~14 min · cuda, nvidia, bandwidth, hbm, gddr7, tensor-cores, vendor-claim

Level 0스펙 시트 훑는 사람
0 XP0/91 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete
"들어가는 모델엔 카드가 더 빨라. 조금이 아니라. 그걸 먼저 말해. 트랙의 나머지는 '들어간다'는 말에 대한 거야."

라이벌을 포함한 메모리 사다리

코드 블록은 모든 단을 사다리 하나에 놓아. 용량, 대역폭, 그 비율, 그리고 물리 트랙이 값 매긴 같은 체크포인트 셋에 각각이 함의하는 디코드 상한. 대역폭 칸을 읽어. GeForce RTX 5090은 32 GB GDDR7에 "1792 GB/sec of total memory bandwidth"를 실어. M3 Ultra의 819의 2.2배. H100은 HBM3 3.35 TB/s, 네 배. H200은 4.8 TB/s. B200은 NVIDIA의 시스템 페이지에서 유도하면 8 근처. 셋 다에 들어가는 27B에 상한은 Studio에서 57, 5090에서 124, H100에서 232, B200에서 555. 카드가 나눗셈을 이기고, 인터페이스 레슨은 이미 인정했어. 버스는 로드할 때 한 번 건너고, 그 뒤 모든 토큰은 풀보다 빠른 메모리에서 디코드돼. M5 Ultra의 "1.2TB/s"는 소비자 카드와의 격차를 좁히고 데이터센터 부품엔 안 닿아.

격차가 더 큰 연산

디코드는 대역폭이고, 프리필과 학습과 이미지 생성은 연산이고, 거기서 비율은 둘이나 넷이 아니라 쉰이야. 실험실은 office의 GPU를 MLX로 fp32 19.5 TFLOP/s, PyTorch로 bf16 21.9로 쟀어. NVIDIA의 H100 페이지는 BF16 텐서 처리량을 "with sparsity" 1,979 TFLOPS로 적어. 그러니 밀집으론 989. FP8은 희소 3,958, 밀집 1,979. Hopper가 FP8을 들여왔고, Blackwell은 4비트 부동소수점을 더하고, 그 정밀도를 돌리는 텐서 코어는 M3 GPU에 대응물이 없어. 애플의 M5 세대는 모든 GPU 코어에 "Neural Accelerators"를 더하고 "up to 4.5x the peak GPU compute for AI compared to M3 Ultra"를 주장해. 이 퀘스트가 재지 않은 벤더 지표고, 액면대로 받아도 데이터센터 부품까지 한 자릿수 차이가 남아. 그래서 곡선 레슨의 프리필 벽, 27B로 32K 프롬프트에 첫 토큰까지 90초는 카드 문제라기보다 맥 문제고, 두 걸음 앞의 학습 레슨이 짧은 이유야.

링크, 그리고 대역폭이라 불리는 두 가지

NVIDIA의 세 번째 우위는 칩 사이야. NVLink 5는 "1.8 TB/s … per GPU"를 나르고, Grace CPU와 Hopper GPU 사이의 NVLink-C2C는 900 GB/s. 애플의 UltraFusion은 M3 Ultra의 다이 둘 사이에 "over 2.5TB/s", M5 Ultra에 "over 4.4TB/s"를 날라. 더 큰 숫자지만 다른 것에 대한 거야. 패키지 하나 안의 다이 간 링크, 실험실이 디코드 커널에 메모리 시스템 대역폭의 작은 몫을 전달한다고 찾아낸 그것이지, 온전한 칩 둘 사이의 링크가 아니야. 맥 둘 사이의 링크는 10 GB/s의 Thunderbolt 5와 이더넷뿐이고, 큰 모델 트랙이 값 매겨. 그러니 라이벌의 사다리엔 맥이 못 오르는 칸이 셋 있어. 들어가는 모델의 메모리 대역폭, 곱하는 모든 것의 텐서 연산, 걸치는 모든 것의 칩 간 링크. 다음 레슨은 NVIDIA가 못 오르는 칸이야.

Code

bandwidth_ladder.py — 벤더 대역폭, 용량, 그리고 그것들이 함의하는 상한·python
#!/usr/bin/env python3
"""Where NVIDIA leads: the memory ladder, vendor figures only, and the decode
ceiling each rung implies for the same 4-bit checkpoints (bytes per token from
the lab's headers: 27B 14.42 GB; a 70B at 4.5 bits ≈ 39.7 GB; a 405B ≈ 228 GB)."""
rungs = [  # name, memory GB, GB/s, source
    ("Apple M3 Ultra (Mac Studio)",        512, 819,  "Apple: 819GB/s"),
    ("Apple M5 Max (MacBook Pro)",         128, 614,  "Apple: 614GB/s"),
    ("Apple M5 Ultra (Mac Studio)",        512, 1229, "Apple: '1.2TB/s'"),
    ("NVIDIA RTX 4090",                     24, 1008, "DERIVED: 21 Gbps x 384-bit / 8"),
    ("NVIDIA RTX 5090",                     32, 1792, "NVIDIA: '1792 GB/sec'"),
    ("NVIDIA RTX PRO 6000 Blackwell",       96, 1792, "NVIDIA datasheet: 1792 GB/s"),
    ("NVIDIA DGX Spark (GB10)",            128, 273,  "NVIDIA: 273 GB/s"),
    ("NVIDIA H100 SXM",                     80, 3350, "NVIDIA: 3.35TB/s"),
    ("NVIDIA H200",                        141, 4800, "NVIDIA: '4.8 terabytes per second'"),
    ("NVIDIA B200 (per GPU)",              180, 8000, "DERIVED from DGX B200 / GB200 pages"),
]
models = [("27B 4-bit", 14.42), ("70B 4-bit", 39.7), ("405B 4-bit", 228.0)]
print(f"{'device':32} {'GB':>4} {'GB/s':>5} {'GB/s per GB':>11} |" + "".join(f" {m[0]:>11}" for m in models))
for name, mem, bw, src in rungs:
    cells = []
    for mname, gb in models:
        cells.append(f"{bw/gb:11.0f}" if gb + 2 <= mem * 0.9 else f"{'no fit':>11}")
    print(f"{name:32} {mem:4d} {bw:5d} {bw/mem:11.1f} |" + " ".join(cells))
print("\nceiling = bandwidth ÷ bytes per token; 'no fit' = weights plus a little headroom exceed 90% of the memory")

# device                             GB  GB/s GB/s per GB |   27B 4-bit   70B 4-bit  405B 4-bit
# Apple M3 Ultra (Mac Studio)       512   819         1.6 |         57          21           4
# Apple M5 Max (MacBook Pro)        128   614         4.8 |         43          15      no fit
# Apple M5 Ultra (Mac Studio)       512  1229         2.4 |         85          31           5
# NVIDIA RTX 4090                    24  1008        42.0 |         70      no fit      no fit
# NVIDIA RTX 5090                    32  1792        56.0 |        124      no fit      no fit
# NVIDIA RTX PRO 6000 Blackwell      96  1792        18.7 |        124          45      no fit
# NVIDIA DGX Spark (GB10)           128   273         2.1 |         19           7      no fit
# NVIDIA H100 SXM                    80  3350        41.9 |        232          84      no fit
# NVIDIA H200                       141  4800        34.0 |        333         121      no fit
# NVIDIA B200 (per GPU)             180  8000        44.4 |        555         202      no fit

External links

Exercise

bandwidth_ladder.py에 네 맥을 벤더 대역폭과 메모리로 더하고, 살 수 있는 카드 하나를 더해. 네가 실제로 돌리는 가장 큰 모델에 대해 상한 둘과 비율을 카드에 적어. 그다음 둘째 줄을 써. 그 모델이 그 카드에 아예 들어가는지.
Hint
들어가면 카드의 상한이 대략 대역폭 비율만큼 높은 쪽이고, 정직한 카드는 그렇게 말해. 안 들어가면 비율은 의미 없고, 채워야 할 건 다음 레슨의 표야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.