GPU를 4장에서 8장으로 늘렸는데 throughput이 1.5배 수준에 그쳤다는 얘기를 현장에서 자주 듣는다. 텐서 병렬의 이론 기대치는 GPU 수만큼 연산이 쪼개지니 거의 선형에 가까운 스케일링인데, 왜 실제는 다를까.
Transformer 레이어가 끝날 때마다 All-Reduce 통신이 반드시 실행된다. 이 통신은 GPU를 늘려도 사라지지 않고, 인터커넥트 종류에 따라 비용이 수십 배 차이 난다. GPU를 늘릴수록 throughput이 선형으로 늘지 않는 원인이 여기 있다.
All-Reduce 발생 위치: 레이어당 정확히 2회
Megatron-LM(Shoeybi et al., 2019)이 제안한 텐서 병렬 구조에서 Transformer 레이어는 두 블록이 각각 All-Reduce를 하나씩 만들어낸다.
MLP 블록은 column-parallel 선형 변환과 row-parallel 선형 변환으로 쪼개진다. 각 GPU가 weight의 일부 열(column)을 들고 독립적으로 partial output을 계산한 뒤, row-parallel 결과를 All-Reduce로 합산해야 다음 레이어에 올바른 activation을 전달할 수 있다. Self-Attention 블록도 동일하다. Q/K/V projection을 헤드 단위로 GPU에 분산하고, output projection 결과를 All-Reduce로 모은다.
레이어당 2회. Llama-3 70B는 레이어가 80개이므로 토큰 1개를 decode할 때마다 160회의 All-Reduce가 발생한다. Prefill은 시퀀스 전체를 한 번에 처리하니 160회지만, decode는 토큰 하나 생성할 때마다 160번이 반복된다. 1000토큰을 생성하면 16만 번이다.
통신량 계산: TP degree의 함수
ring All-Reduce에서 GPU당 실제 전송 바이트는 아래 식으로 계산된다.
전송 바이트 = 2 × (TP-1)/TP × batch_size × seq_len × hidden_dim × sizeof(dtype)
Decode 단계는 seq_len=1이고, 배치 1, FP16(2바이트) 기준으로 Llama-3 70B(hidden_dim=8192)를 대입하면:
| TP | (TP-1)/TP | 레이어당 All-Reduce 전송 | 80레이어 × 2회 합산 |
|---|---|---|---|
| 2 | 0.500 | 16 KB | 2.56 MB |
| 4 | 0.750 | 24 KB | 3.84 MB |
| 8 | 0.875 | 28 KB | 4.48 MB |
TP=2에서 8로 올려도 레이어당 전송량은 16 KB → 28 KB, 1.75배 증가에 그친다. 수치 자체는 크지 않다. 문제는 이 통신 160회가 직렬로 실행된다는 데 있다. 이전 All-Reduce가 완료되기 전까지 다음 레이어 연산을 시작할 수 없으므로, 1회당 레이턴시가 쌓이는 방식으로 병목이 형성된다.
인터커넥트 토폴로지별 실효 대역폭
NCCL은 intra-node에서 ring All-Reduce를 기본 알고리즘으로 사용한다. ring 방식은 N개 GPU에서 2(N-1)번의 send/recv 단계를 거치기 때문에 aggregate 이론 대역폭을 그대로 활용하지 못한다. nccl-tests all_reduce_perf로 이 차이를 확인할 수 있다.
# 4-way GPU all-reduce, 1MB~256MB 메시지 스위프
./build/all_reduce_perf -b 1M -e 256M -f 2 -g 4
A100 SXM 8-way(NVLink 3세대, aggregate 이론치 600 GB/s) 환경에서 256MB 메시지 기준 bus bandwidth 실측치는 약 200225 GB/s다. point-to-point 테스트에서 430520 GB/s가 나오는 것과 비교하면 ring All-Reduce 실효는 P2P의 절반 수준이다.
PCIe 4.0 환경은 완전히 다른 세계다. GPU들이 CPU를 경유해 간접 연결될 때 4-way all-reduce의 algorithm bandwidth는 13.6 GB/s, bus bandwidth는 약 20 GB/s까지 떨어진다. NVLink 대비 1/10 이하다. 노드 간 InfiniBand HDR는 200 Gb/s(≈25 GB/s)인데, 다중 노드 all-reduce는 ring 최외곽 경로가 IB를 타므로 노드 내 NVLink 대역폭과 무관하게 IB 대역폭이 전체 병목이 된다.
TP=4, batch=1 기준 24 KB All-Reduce의 이론적 전송 지연을 환경별로 환산하면:
| 인터커넥트 | 실효 버스 대역폭 | 24 KB 이론 지연 | 1토큰(160회) 누적 |
|---|---|---|---|
| NVLink A100 SXM | ~200 GB/s | ~0.12 µs | ~19 µs |
| PCIe 4.0 (CPU 경유) | ~20 GB/s | ~1.2 µs | ~192 µs |
| InfiniBand HDR | ~25 GB/s | ~0.96 µs | ~154 µs |
이 수치는 순수 전송 시간만 계산한 하한값이다. 실제 NCCL All-Reduce에는 커널 런치 오버헤드, 프로토콜 핸드셰이크, 동기화 대기가 더해진다. 24 KB처럼 작은 메시지에서 실측 지연은 이보다 크다. Llama-3 70B TP=4 batch=1 기준 decode 한 스텝이 약 15~20ms 수준(GPU당 weight 35 GB를 HBM 2 TB/s로 읽는 시간이 지배)임을 고려하면, PCIe 환경에서 All-Reduce 오버헤드가 전체 스텝 시간에서 차지하는 비중은 무시할 수 없는 수준이다.
All-Reduce 구간을 직접 확인하고 싶다면 nsys로 프로파일링한다:
nsys profile --trace=cuda,nccl --output profile_tp4 python run_inference.py
Nsight Systems GUI에서 NCCL 커널 타임라인을 CUDA 연산과 나란히 놓으면 All-Reduce 구간과 다음 GEMM 시작까지의 gap이 눈에 들어온다. 이론 계산보다 직접 보는 게 설득력 있다.
Arithmetic Intensity로 보는 통신-연산 비율 변화
Decode 단계는 메모리 대역폭에 묶인 연산이다. batch=1, seq_len=1 조건에서 GEMM의 arithmetic intensity는 약 1~2 FLOP/Byte다. Llama-3 70B TP=4 기준 GPU당 전체 weight는 약 35 GB(70B parameters × 2 bytes ÷ 4)이고, batch=1 decode는 그 weight를 한 번 읽어 35G FLOP을 수행하니 AI ≈ 1 FLOP/Byte가 된다. A100의 roofline 교차점이 312 TFLOPS ÷ 2 TB/s = 156 FLOP/Byte이므로, decode는 교차점의 1/150 수준에서 동작한다. 연산 유닛은 대부분 놀고 있다.
배치 크기가 늘면 달라진다. batch=32이면 같은 weight를 읽으면서 32배 많은 연산을 수행하니 AI ≈ 32 FLOP/Byte로 올라간다. 여전히 memory-bound지만, 레이어당 실제 연산 시간이 길어진다. All-Reduce의 절대 지연은 그대로인데 GEMM 시간이 늘어나므로 통신이 차지하는 상대 비율이 줄어든다.
저배치 실시간 서빙에서 TP를 올릴수록 통신 오버헤드 비중이 상대적으로 커지고, 고배치 throughput 서빙에서는 HBM 압박 분산으로 얻는 이득이 통신 비용을 압도한다. TP가 이득인 구간 자체가 배치 크기에 따라 이동한다.
실전 판단: TP를 올리면 오히려 손해인 조건
| 모델 크기 | 배치 | 인터커넥트 | 권장 TP | 판단 근거 |
|---|---|---|---|---|
| 70B | 1~4 | NVLink | 4 | TP=8 대비 통신 비율 증가, latency 이득 미미 |
| 70B | 1~4 | PCIe | 최소 필요 TP | 통신이 decode 지연을 지배 |
| 70B | 32+ | NVLink | 8 | HBM 분산 이득 > 통신 오버헤드 |
| 70B | 32+ | PCIe | 4 이하 | PCIe 통신 비용 > 메모리 분산 이득 |
| 13B 이하 | 무관 | 싱글 노드 | 1 (가능 시) | All-Reduce 자체 제거 |
| 140B+ 다중 노드 | 무관 | InfiniBand | 노드 내 최소화 | IB 병목, PP 병용 고려 |
PCIe 서버에서 TP=8은 거의 항상 손해다. NVLink 환경에서도 batch 1~4 실시간 서빙에서는 TP=8과 TP=4의 실측 throughput 차이가 작거나 역전되는 경우가 있다. 모델이 단일 GPU에 올라가지 않아 어쩔 수 없이 TP를 올려야 하는 상황이 아닌 한, 모델이 딱 들어가는 최소 TP degree에서 시작해 nsys로 직접 확인하는 게 안전하다.
Async Overlap의 현실적 한계
vLLM과 Megatron-LM 모두 async All-Reduce로 통신과 연산을 겹치려는 시도를 한다. Prefill 단계에서는 효과적이다. 시퀀스 길이가 길어서 레이어당 GEMM 시간이 수ms~수십ms로 길고, 그 구간에 All-Reduce를 끼워 넣을 공간이 충분하다.
Decode 단계는 구조가 다르다. batch=1 기준 레이어당 GEMM 시간이 수십~수백 µs 수준에 불과하다. NVLink 환경에서는 All-Reduce 자체가 워낙 빠르니 overlap 여부가 중요하지 않고, PCIe 환경에서는 All-Reduce가 길어서 숨길 연산 구간 자체가 부족하다. TokenWeave(2025)처럼 operation을 세밀하게 분해해 decode overlap 효율을 높이려는 연구가 나오는 것도 이 구조적 한계 때문이다.