Fault tolerant distributed training on Amazon EKS using NVRx
Quick Summary
Amazon EKS의 PyTorch FSDP 학습에 NVRx를 결합해 비동기 체크포인팅으로 저장 대기를 줄이고, 장애 유형에 따라 프로세스 내부 재시작과 ft launcher로 학습을 복구하는 구성을 설명한다.
🖼️ 인포그래픽

🖼️ 4컷 인포그래픽

💡 한 줄 요약
Amazon EKS의 PyTorch FSDP 학습에 NVRx를 결합해 비동기 체크포인팅으로 저장 대기를 줄이고, 장애 유형에 따라 프로세스 내부 재시작과 ft_launcher로 학습을 복구하는 구성을 설명한다.
📌 핵심 요약
- 대규모 분산 학습에서는 단일 GPU 장애가 NCCL 타임아웃과 다른 워커의 중단으로 확산될 수 있으며, 원문이 다룬 클러스터 규모에서는 동기 체크포인팅이 전체 경과 시간의 최대 40%를 차지했다.
- NVRx의 TorchAsyncCheckpoint는 저장을 백그라운드 프로세스로 넘겨 학습과 I/O를 겹치고, FSDP LOCAL_STATE_DICT를 사용해 각 rank가 all-gather나 rank 0 병목 없이 자체 샤드를 저장한다.
- inprocess.Wrapper는 예외와 NCCL 멈춤 같은 소프트 장애를 처리하고, ft_launcher는 SIGKILL·OOM 종료·운영체제 수준의 멈춤 같은 하드 장애에서 워커를 다시 생성한다. 노드 손실은 클러스터 오케스트레이터가 담당한다.
- 실행 환경은 노드당 NVIDIA H100 80 GB GPU 8개와 EFA 인터페이스 32개를 갖춘 p5.48xlarge 기반 Amazon EKS이며, 같은 가용 영역의 Amazon FSx for Lustre를 체크포인트 공유 저장소로 사용한다. 규모가 커지면 복구 시간은 재시작 자체보다 체크포인트 로딩의 영향을 크게 받는다.
- 원문은 H100 GPU의 2~8노드 벤치마크를 소개하며, 재현에는 PyTorch 2.9+와 NVRx 0.4.1, 현재 배포에는 런처 설정을 갱신한 NVRx 0.6.0을 안내한다. 다만 제공된 본문은 inprocess.Wrapper 호출 코드 중간에서 끝나 구체적인 성능 비교 결과는 확인할 수 없다.
🧩 주요 포인트
- 체크포인트 쓰기 경로와 장애 복구는 독립적인 변경 축 → 저장 대기와 장애 중단 중 실제 문제에 맞춰 NVRx 기능을 선택적으로 도입할 수 있다.
- 소프트 장애·하드 장애·노드 손실의 처리 범위가 다름 → inprocess.Wrapper, ft_launcher, 클러스터 오케스트레이터의 역할을 구분해야 한다.
- 공유 체크포인트 로딩이 규모 확장 시 복구 시간을 좌우함 → Amazon FSx for Lustre의 배치와 읽기 지연을 복구 성능 평가에 포함해야 한다.
🧠 상세 정리
1. 대규모 분산 학습의 두 가지 중단 비용
대규모 분산 학습은 수십 개 노드에서 수시간 또는 수일 동안 실행되므로, 네트워크 분할·메모리 오류·소프트웨어 예외·인프라 이벤트에 따른 중단을 통계적으로 피하기 어렵다는 문제에서 출발한다. 단일 GPU 장애도 NVIDIA Collective Communication Library인 NCCL의 타임아웃을 정상 워커로 전파하고, Pod가 서로 다른 시점에 종료되거나 재시작되는 연쇄 반응을 일으킬 수 있다. 이때 클러스터는 학습 진전 없이 GPU 시간을 소비한다. 별도의 유휴 시간 원인은 동기 체크포인팅으로, 저장할 때마다 모든 rank가 I/O를 기다리며 원문이 다룬 클러스터 규모에서는 전체 경과 시간의 최대 40%를 차지했다. 글은 이 두 문제를 해결하기 위해 Amazon EKS의 PyTorch FSDP 학습에 NVRx를 통합하는 방법을 제시한다.
2. NVRx와 인프라의 역할 분담
솔루션은 애플리케이션 수준의 복원력을 담당하는 NVRx와 다중 노드 GPU 학습 기반을 제공하는 Amazon EKS를 결합한다. NVRx는 pip로 설치하는 Python 계층이며, 별도 커널이나 PyTorch 포크 또는 재컴파일 없이 기존 FSDP 스크립트에서 일반적인 import 방식으로 사용할 수 있다고 설명한다. 모델과 학습 코드는 유지하면서 비동기 체크포인팅, 프로세스 내부 재시작, ft_launcher를 통한 작업 내 재시작을 각각 독립적으로 도입하는 구상이다. Amazon EKS 환경은 GPU 스케줄링과 고대역폭 네트워크, 체크포인트를 보존할 공유 저장소를 맡는다. 특히 체크포인트 쓰기 최적화와 장애 복구를 서로 독립적인 변경으로 구분하며, 예제도 기능별 스크립트로 제공해 필요한 기능만 선택하도록 구성한다.
3. 장애 유형에 따른 복구 계층
프로세스 내부 재시작은 inprocess.Wrapper로 학습 함수를 감싸 처리되지 않은 예외나 NCCL 멈춤이 Python 프로세스 종료로 이어지는 것을 막는 방식이다. NVRx는 활성 프로세스 그룹을 중단하고 rank별 GPU·NVLink·NIC 상태를 확인한 뒤, 살아남은 워커를 다시 연결해 최신 체크포인트에서 학습 함수로 재진입한다고 설명한다. 이 과정에서 인터프리터와 CUDA 할당기, 함수 바깥 범위의 객체는 유지된다. 반면 ft_launcher는 각 rank의 RankMonitorClient가 보내는 하트비트를 명시적인 CLI 타임아웃과 비교해 SIGKILL, OOM 종료, 운영체제 수준의 멈춤을 감지한다. 워커가 멈추거나 종료되면 생존 워커도 종료하고 GPU 메모리를 회수한 후 같은 작업 안에서 새 워커를 생성하며, 노드 손실은 별도로 클러스터 오케스트레이터의 처리 범위로 둔다.
4. Amazon EKS의 GPU·네트워크·저장소 구성
Amazon EKS는 제어 영역과 업그레이드, API 서버 가용성을 관리하고, 학습에는 p5.48xlarge 인스턴스의 자체 관리형 노드 그룹을 사용한다. 각 노드는 NVIDIA H100 80 GB GPU 8개와 EFA 네트워크 인터페이스 32개를 제공하며, 원문은 NCCL all-reduce용 EFA 네트워크 대역폭을 3,200 Gbps로 제시한다. 학습 Pod는 Kubernetes Job으로 실행하고 헤드리스 Service와 DNS를 이용해 워커를 발견하므로 고정 IP 없이 교체된 Pod가 다시 참여할 수 있다. NVIDIA 및 EFA 디바이스 플러그인은 자원을 스케줄러에 노출하고, 노드 선호도와 toleration 설정은 노드당 GPU 8개를 할당하는 배치를 지원한다. 체크포인트는 FSx CSI 드라이버로 모든 학습 Pod에 마운트한 Amazon FSx for Lustre의 SCRATCH_2, 1.2 TB 파일시스템에 저장하며, 복구 시 읽기 지연을 줄이도록 GPU 노드와 같은 가용 영역에 배치한다.
5. 사전 준비와 버전 구분
사전 조건에는 p5.48xlarge 또는 p4de.24xlarge 인스턴스 서비스 할당량이 있는 AWS 계정과 Amazon EKS v1.28 이상 클러스터가 포함된다. GPU 노드 그룹에는 EFA가 활성화되어 있어야 하고 NVIDIA 디바이스 플러그인이 설치되어야 하며, SCRATCH_2 유형의 Amazon FSx for Lustre는 GPU 노드와 같은 가용 영역에 있어야 한다. 벤치마크 재현용 컨테이너에는 PyTorch 2.9 이상과 NVRx 0.4.1을 사용하지만, 현재 배포에는 런처 설정을 갱신한 NVRx 0.6.0을 안내한다. 학습 코드를 포함한 이미지는 Amazon ECR에 올리고 kubectl을 클러스터에 연결하며, 예제 모델인 meta-llama/Llama-3.1-8B에 접근 가능한 HuggingFace 계정도 준비한다. 데이터는 공유 저장소에 미리 내려받으며 원문은 C4 데이터셋의 100K 샘플을 사용하되 다른 모델이나 데이터셋도 선택할 수 있다고 명시한다.
6. 동기 체크포인팅을 사용하는 기준 학습
구현 설명은 torchrun으로 실행하는 최소한의 FSDP 학습 루프에서 시작하며, 이 기준 스크립트는 동기식 분산 체크포인트 저장을 사용한다. 각 프로세스는 환경 변수에서 rank와 world size, local rank를 읽고 CUDA 장치를 지정한 다음 NCCL 기반 분산 프로세스 그룹을 초기화한다. 이후 모델을 생성해 FSDP로 감싸고 AdamW 옵티마이저와 데이터 반복자를 구성한 뒤 학습 스텝을 진행한다. 지정된 체크포인트 간격마다 호출하는 save_checkpoint는 내부적으로 PyTorch의 torch.distributed.checkpoint.save를 사용하므로 각 rank의 샤드가 공유 저장소에 기록될 때까지 모든 rank가 대기한다. 이 기준 구성에서는 워커 하나가 종료되면 전체 학습 작업이 실패해 마지막 체크포인트부터 작업을 완전히 다시 시작해야 하며, 이후 소개하는 기능들은 이러한 저장 대기와 복구 방식을 각각 개선하는 변경이다.
7. 비동기 체크포인트의 저장 흐름
비동기 방식에서는 모델과 옵티마이저 설정 이후 TorchAsyncCheckpoint를 persistent_queue=True로 한 번 생성하고, 저장 시 async_save에 상태 사전과 경로를 전달한다. 실제 쓰기는 백그라운드 프로세스가 맡고 호출은 즉시 반환하므로 주 학습 흐름은 다음 순전파와 역전파 단계로 진행할 수 있다. 예제의 상태 사전은 FSDP LOCAL_STATE_DICT를 사용해 CPU에 준비되며, 각 rank가 자체 샤드를 직접 쓰므로 all-gather나 rank 0에 집중되는 저장 병목을 피한다. 개요에서는 다음 저장 전에 finalize_async_save로 이전 쓰기를 완료한다고 설명하고, 제시된 코드에서는 작업 종료 시 finalize_async_save(blocking=True)를 호출해 진행 중인 저장을 마무리한다. 따라서 본문은 비동기 저장 요청의 즉시 반환과 실제 쓰기 완료를 구분하며, 예제 코드에는 종료 시 완료를 기다리는 절차가 명시되어 있다.
8. 프로세스 내부 재시작 설정과 자료의 범위
inprocess.Wrapper의 생성자는 소프트·하드·배리어·완료 타임아웃, 상태 검사, 재시도 제어, rank 할당이라는 네 가지 관심사를 연결한다. 제시된 구성은 CudaHealthCheck와 FaultCounter를 조합하고 max_rank_faults를 20으로 설정하며, RetryController에는 최대 재시작 횟수 인자와 최소 활성 world size 1을 전달한다. ActivateAllRanks와 ShiftRanks는 생존 rank를 연속적인 배치로 정리하고, 감싸진 학습 함수는 분산 환경 재초기화와 FSDP 재구성, 최신 체크포인트 로딩을 수행하도록 설명된다. 함수 주석은 매 스텝 call_wrapper.ping()을 호출하고 call_wrapper.iteration으로 재시작 회차를 확인하는 방식도 제시한다. 다만 제공된 본문은 wrapped_train 호출 중간에서 끊기므로, 서두에서 예고한 H100 기반 2~8노드 벤치마크의 상세 결과나 이후 복구 계층 조합 설명까지 확인할 수는 없다.
🧾 핵심 주장 / 시사점
- 비동기 체크포인팅은 정상 학습 중 저장 대기를 줄이고 재시작 기능은 장애 이후 중단을 줄이므로, 두 기능의 효과를 서로 다른 비용 항목으로 이해할 수 있다.
- 프로세스를 유지하는 복구와 새 워커를 생성하는 복구는 대응하는 장애가 다르므로, 한 가지 재시작 방식만으로 모든 장애를 포괄한다고 해석해서는 안 된다.
- 재시작 절차가 빨라도 체크포인트 로딩이 오래 걸리면 전체 복구가 지연되므로, 공유 저장소의 읽기 지연은 복원력 설계의 주요 요소다.
✅ 액션 아이템
- 동기 체크포인팅의 대기 비용을 기준으로 TorchAsyncCheckpoint와 FSDP LOCAL_STATE_DICT 적용 필요성 검토.
- 소프트 장애·하드 장애·노드 손실에 맞춰 inprocess.Wrapper, ft_launcher, 클러스터 오케스트레이터의 복구 범위 구분.
- Amazon FSx for Lustre의 동일 가용 영역 배치와 체크포인트 로딩 지연을 복구 성능 평가에 반영.
❓ 열린 질문
- 동기 체크포인팅이 전체 경과 시간의 최대 40%를 차지한 환경에서 TorchAsyncCheckpoint 적용 후 저장 대기는 얼마나 감소했는가?
- inprocess.Wrapper와 ft_launcher는 각각 소프트 장애와 하드 장애에서 어느 정도의 복구 시간을 보였는가?
- H100 GPU의 2~8노드 규모에서 Amazon FSx for Lustre의 체크포인트 로딩 시간은 어떻게 달라졌는가?