분산 LLM 학습 01 - 왜 LLM 학습은 분산 시스템 문제가 되는가
여러 GPU를 붙이는 순간 학습 코드는 계산만의 문제가 아니라 메모리와 통신, 장애 복구까지 포함한 시스템 문제가 된다
이 시리즈를 어떤 관점으로 읽어야 할까?
LLM 분산 학습을 처음 접하면 보통 프레임워크 이름부터 보게 된다. DDP, FSDP, ZeRO, Megatron-LM, DeepSpeed 같은 이름을 먼저 외우기 시작하면 금방 길을 잃는다. 실제로 중요한 것은 이름이 아니라, 왜 그런 기법이 등장했는지 이해하는 것이다.
분산 학습은 결국 세 가지 자원을 동시에 다루는 문제다.
- 계산량을 여러 장치에 어떻게 나눌 것인가
- 메모리 사용량을 어떻게 감당할 것인가
- 장치 사이 통신 비용을 어떻게 숨길 것인가
LLM에서는 이 세 가지가 모두 커진다. 파라미터 수가 크고, activation도 크고, optimizer state까지 포함하면 메모리 사용량은 생각보다 훨씬 빠르게 불어난다. 동시에 GPU를 여러 장 붙이면 계산량은 분산할 수 있지만, gradient와 activation을 주고받아야 하므로 통신 비용이 새 병목으로 등장한다.
단일 GPU에서 보던 감각이 왜 깨질까?
단일 GPU에서는 "한 step이 오래 걸린다" 정도로 보이던 문제가 분산 환경에서는 여러 층으로 갈라진다.
- 어떤 step은 forward/backward 계산이 오래 걸린다
- 어떤 step은 all-reduce가 오래 걸린다
- 어떤 step은 dataloader가 뒤처져서 GPU가 빈다
- 어떤 run은 메모리 부족 때문에 batch size를 줄여야 한다
- 어떤 run은 한 rank만 느려져서 전체 step이 늦어진다
즉, 분산 학습은 더 이상 "모델 학습 코드"만 보는 일이 아니다. 네트워크 토폴로지, 프로세스 배치, collective 통신, 메모리 복제, 장애 복구, checkpoint 전략까지 함께 봐야 한다.
Distributed Training Engineer가 실제로 하는 일
이 역할은 단순히 여러 GPU를 띄우는 사람이 아니다. 실무에서는 다음 질문에 답할 수 있어야 한다.
- 지금 병목이 계산인가, 메모리인가, 통신인가?
- data parallel만으로 충분한가, 아니면 sharding이 필요한가?
- tensor parallel이나 pipeline parallel을 쓰면 어떤 비용이 새로 생기는가?
- global batch size를 키웠을 때 optimizer 동작과 학습 안정성은 어떻게 달라지는가?
- 장애가 났을 때 run을 어떻게 이어갈 것인가?
이런 질문은 프레임워크 사용법만 익혀서는 답하기 어렵다. 내부 동작을 알아야 한다.
이 시리즈의 구성
이 시리즈는 다음 흐름으로 간다.
- synchronous SGD와 data parallel의 기본 구조
- all-reduce와 collective 통신의 실제 비용
- PyTorch DDP 내부 동작
- LLM 학습에서 메모리가 어떻게 소모되는지
- NCCL과 하드웨어 토폴로지가 성능에 주는 영향
- tensor parallel, sequence parallel, pipeline parallel
- activation checkpointing, ZeRO, FSDP
- overlap, checkpoint, 장애 복구, 디버깅
- Megatron-LM과 DeepSpeed 같은 프레임워크가 무엇을 추상화하는지
- 실제 학습 스택을 어떻게 설계할지
이 시리즈를 공부할 때의 기준
각 글을 읽을 때는 "이 기법이 무엇을 줄이려는가?"를 계속 물어보는 편이 좋다.
- 메모리 복제를 줄이는가?
- 통신 횟수를 줄이는가?
- 통신과 계산을 겹치는가?
- idle time을 줄이는가?
- 특정 토폴로지에서 더 잘 맞는가?
이 질문이 잡히면 이후의 프레임워크 글도 훨씬 덜 추상적으로 읽힌다.
다음 글에서는 가장 기본이 되는 synchronous SGD와 data parallel을 먼저 정리한다. 분산 학습의 거의 모든 전략은 결국 여기서 출발한다.