분산 구성 간 성능 비교 — 시드·배치·학습률
분산 구성 간 성능 비교 — 시드·배치·학습률
TPU, 멀티 GPU, 단일 GPU는 같은 스크립트를 같은 배치 크기로 돌려도 결과가 정확히 맞아떨어지지는 않아요. 왜 그런지, 그리고 비교할 때 무엇을 맞춰야 하는지 세 가지 축으로 정리해볼게요.
출처: https://huggingface.co/docs/accelerate/concept_guides/performance
시드 설정
재현 가능한 훈련을 위해 모든 분산 케이스에서 시드를 완전히 설정하는 게 좋아요. utils.set_seed()가 이를 대신해줍니다.
from accelerate.utils import set_seed
set_seed(42)
이 함수는 내부적으로 5가지 시드 설정을 하나로 묶어줘요.
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed) # or torch.xpu.manual_seed_all, etc
# ^^ safe to call this function even if cuda is not available
if is_torch_xla_available():
xm.set_rng_state(seed)
random·numpy·torch·torch 디바이스, 그리고 TPU가 있으면 torch_xla의 cuda 상태까지 함께 설정됩니다.
관측 배치 크기(Observed Batch Size)
Accelerate로 훈련할 때 DataLoader에 넘기는 배치 크기는 GPU당 배치 크기예요. 즉 두 GPU에서 배치 64는 실제로는 배치 128이 됩니다. 단일 GPU에서 비교 테스트를 할 때는 이 점을 반드시 반영해야 해요.
| Single GPU Batch Size | Multi-GPU Equivalent Batch Size | TPU Equivalent Batch Size |
|---|---|---|
| 256 | 128 | 32 |
| 128 | 64 | 16 |
| 64 | 32 | 8 |
| 32 | 16 | 4 |
이 표는 "Multi-GPU"가 두 GPU, TPU pod가 8 워커인 경우의 예시예요.
학습률
문서들이 공통으로 지적하듯 학습률은 디바이스 수에 따라 선형적으로 스케일해야 해요. Accelerate로는 이렇게 적용합니다.
learning_rate = 1e-3
accelerator = Accelerator()
learning_rate *= accelerator.num_processes
optimizer = AdamW(params=model.parameters(), lr=learning_rate)
학습률 스케일 여부는 사용자 판단에 맡기고 Accelerate가 강제하지 않아요. 또 accelerate는 학습 중인 프로세스 수에 따라 학습률 스텝을 밟습니다. 앞서 말한 관측 배치 크기 때문인데, 두 GPU면 단일 GPU보다 학습률이 두 배 자주 스텝되어 더 큰 배치를 보정합니다.
그라디언트 누적과 혼합 정밀도
그라디언트 누적과 혼합 정밀도를 쓸 때, 그라디언트 평균 방식과 정밀도 손실 때문에 배치 단위 loss는 구성 간에 어느 정도 저하가 생기는 게 정상이에요. 하지만 훈련이 끝난 뒤 전체 loss·메트릭·일반 성능은 대략적으로 같아야 합니다.
더 알아보기
- 설치와 설정은 Installation 참고
- 스크립트 실행은 Launching scripts 참고
- 노트북 실행은 Jupyter Notebook 참고