IL-0129 Hugging Face · 2025-10-30 (게시일)ai-infraaws
Hugging Face 는 고정 Slurm 예약으로 잡은 48개 노드의 H100 GPU 384개에서 SmolLM3 를 한 달 가까이 학습했다. 본 학습 직전에 같은 48개 노드에서 처리량 검증을 마쳤지만, 시작하고 몇 시간 만에 처리량이 크게 떨어졌다. 서로 다른 원인 두 가지가 겹쳐 있었다.
첫째 원인은 스토리지였다. 팀은 24 TB 데이터셋을 /fsx 에 마운트된 WekaFS 에 두었다. Weka 는 자주 읽는 파일을 로컬에 두고, 용량이 차면 오래 읽지 않은 파일을 S3 로 내보내는 방식으로 동작한다. 여러 팀이 이미 쓰고 있던 용량에 24 TB 가 더해지자 Weka 가 한계에 닿았다. Weka 는 학습 도중 데이터셋 샤드를 내보내기 시작했다. 내보낸 샤드를 다시 가져오는 동안 학습이 멈췄고, 그래서 처리량이 크게 떨어졌다. 팀은 데이터셋 폴더를 학습 내내 자주 읽는 상태로 고정할 방법을 찾지 못했다. S3 에서 바로 스트리밍하는 방식은 느렸다. 그래서 데이터를 각 노드의 로컬 NVMe RAID 스크래치 스토리지에 두었다. 이 방식에는 노드가 죽어 교체되면 새 노드에 데이터가 없다는 문제가 있었다. 팀은 데이터셋을 미리 올린 예비 노드를 두어 이 문제를 풀었다.
둘째 원인은 데이터로더였다. SmolLM2 는 Megatron-LM 에서 가져온 TokenizedBytes 데이터로더로 안정된 처리량을 냈다. SmolLM3 에서는 Nanotron 에 내장된 nanosets 데이터로더로 바꿨다. 팀은 이 데이터로더로 대규모 사전 학습을 해 본 적이 없었다. nanosets 는 학습 스텝마다 커지는 거대한 인덱스 하나를 단순한 방식으로 만들고 있었다. 스텝 수가 아주 크면 공유 메모리 사용량이 늘었고, 그 때문에 처리량이 급락했다. 팀은 내부 SmolLM2 프레임워크에서 TokenizedBytes 로 같은 설정을 돌려, 48개 노드에서 급락이 없다는 것을 확인했다. 그다음 이 데이터로더를 Nanotron 에 복사해 넣었다. 새 데이터로더는 문서 안의 시퀀스를 차례대로 읽었고, 그 탓에 손실 곡선이 거칠어졌다. 팀은 시퀀스를 오프라인에서 미리 섞은 뒤 학습을 다시 시작했다. 이번에는 처리량이 일정하게 유지됐다.
Hugging Face 팀은 SmolLM3 본 학습을 시작했다. 48개 노드의 H100 GPU 384개로 11T 토큰을 학습하는 일정이었다. 시작하고 몇 시간 안에 처리량이 가파르게 떨어졌고, 이런 급락이 여러 번 되풀이됐다. 처리량은 학습 중 초당 처리하는 토큰 수다. 처리량이 50% 떨어지면 한 달짜리 학습이 두 달짜리가 된다.
같은 48개 노드에서 미리 돌린 처리량 어블레이션 실험에서는 이런 일이 없었다. 어블레이션은 구성 요소 하나씩을 바꿔 가며 영향을 재는 작은 실험이다. 본 학습에서 바뀐 것은 셋이었다. 첫째, 데이터셋이 작은 부분집합에서 약 24 TB 전체로 커졌다. 둘째, 학습 스텝 수가 100B 토큰 실험 길이에서 11T 토큰에 맞는 실제 값으로 늘었다. 셋째, 오래 부하를 받은 하드웨어의 상태가 달라졌을 수 있었다. 노드 수, 데이터로더 설정, 모델 레이아웃, 병렬화 설정은 그대로였다.
팀은 데이터셋 크기나 스텝 수가 처리량을 떨어뜨릴 리 없다고 보고 먼저 하드웨어를 의심했다. 노드 모니터링 지표를 보니 처리량이 크게 떨어진 시점과 디스크 읽기 지연이 급증한 시점이 겹쳤다. 팀은 데이터 스토리지를 살폈고, Weka 가 학습 도중 데이터셋 샤드를 S3 로 내보내고 있다는 것을 알아냈다.
데이터를 각 노드의 로컬 NVMe 로 옮긴 뒤에도 급락은 한 번씩 계속 나타났다. 이번에는 하드웨어 모니터링 지표에 이상이 없었다. 어블레이션 때와 비교하면 급락은 오히려 훨씬 가팔라졌다. 팀은 여전히 하드웨어를 의심해 노드 수를 줄여 가며 시험했다. 그러자 어느 노드를 고르든 노드 하나만으로도 똑같은 급락이 재현됐다. 하드웨어가 원인에서 빠지자 남은 변수는 스텝 수였다. 스텝 수를 3M 에서 32k 로 줄이자 급락이 작아졌다. 스텝 수가 클수록 급락은 더 가파르고 잦았다.
증상 ? 처리량 저하
팀은 학습 중 초당 토큰 처리량을 기록하고 있었다. 학습을 시작하고 몇 시간 안에 이 값이 급락하는 것이 보였다. SmolLM3 에서 기대한 처리량은 초당 13,500에서 14,000 토큰이었다. 팀은 처리량이 이 범위를 계속 벗어나면 위험 신호로 보았다. 그리고 노드 모니터링 지표에서 처리량이 떨어진 시점과 디스크 읽기 지연이 급증한 시점이 겹치는 것을 보고 스토리지를 원인으로 짚었다.
–
마감이 급할 때는 자기 구현을 디버깅하는 것보다 검증된 해법이나 빠른 우회책을 가져오는 편이 빠를 수 있다. 팀은 nanosets 의 인덱스 구현을 고치는 대신 TokenizedBytes 데이터로더를 가져왔다. 손실 문제도 데이터로더에 손대지 않고 오프라인에서 시퀀스를 미리 섞어 풀었다. 다만 임시방편을 너무 많이 쓰면 유지보수와 최적화가 어려운 누더기 시스템이 된다. 팀은 어블레이션과 본 학습 사이에 무엇이 바뀌었는지 정확히 알고 있었기 때문에 데이터셋 크기, 스텝 수, 하드웨어 상태를 하나씩 지워 가며 원인을 좁힐 수 있었다. 두 번째 문제는 처리량이 안정됐던 SmolLM2 의 데이터로더를 대규모로 검증하지 않은 데이터로더로 바꾸면서 생겼다.
같은 원인 · 공통 공유 네트워크 파일 시스템