{"id":"IL-0129","org":"Hugging Face","date":"2025-10-30","docs":[],"title":{"en":"Throughput of the 384-GPU SmolLM3 pretraining run collapsed because shared WekaFS storage evicted dataset shards to S3, then kept dropping on local NVMe because the nanotron dataloader built an index that grew with the step count","ko":"SmolLM3 사전 학습에서 공유 Weka 스토리지가 데이터셋 샤드를 S3 로 내보내고 Nanotron 데이터로더의 인덱스가 스텝마다 커지면서, 학습을 시작한 지 몇 시간 만에 처리량이 거듭 급락했다."},"domain":["ai-infra","aws"],"impact":{"scope":"SmolLM3 pretraining run on 384 H100 GPUs (48 nodes); throughput fell steeply within hours of launch","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Ablations on data subsets and a short step horizon did not exercise either cause: a shared cache-and-evict filesystem near its capacity, and a dataloader index that grows with the step count. Reproducing the drops on one node separated hardware from software, and varying only the step count pointed at the dataloader.\n\nThe team chose proven replacements over repairs under deadline pressure, taking an existing dataloader instead of fixing nanosets and offline shuffling instead of changing the dataloader, and warns that too many such shortcuts leave a patchwork system that is hard to maintain.","ko":"마감이 급할 때는 자기 구현을 디버깅하는 것보다 검증된 해법이나 빠른 우회책을 가져오는 편이 빠를 수 있다. 팀은 nanosets 의 인덱스 구현을 고치는 대신 TokenizedBytes 데이터로더를 가져왔다. 손실 문제도 데이터로더에 손대지 않고 오프라인에서 시퀀스를 미리 섞어 풀었다. 다만 임시방편을 너무 많이 쓰면 유지보수와 최적화가 어려운 누더기 시스템이 된다. 팀은 어블레이션과 본 학습 사이에 무엇이 바뀌었는지 정확히 알고 있었기 때문에 데이터셋 크기, 스텝 수, 하드웨어 상태를 하나씩 지워 가며 원인을 좁힐 수 있었다. 두 번째 문제는 처리량이 안정됐던 SmolLM2 의 데이터로더를 대규모로 검증하지 않은 데이터로더로 바꾸면서 생겼다."},"related":[],"sources":[{"url":"https://huggingfacetb-smol-training-playbook.hf.space/","kind":"blog","license":"unknown","archived":null}],"summary":{"en":"The training data was first stored on /fsx, a WekaFS network filesystem that keeps frequently read files in its local cache and evicts inactive files to S3 as capacity fills. The 24 TB SmolLM3 dataset, together with storage already used by several other teams, pushed Weka to its limit, and it began evicting dataset shards in the middle of training. Each evicted shard had to be fetched back, which stalled the run. The team found no way to pin the dataset folders as hot for the whole run, and streaming straight from S3 was slow, so the data was copied to the local NVMe RAID scratch storage on every node (8 x 3.5 TB drives per node).\n\nLocal storage brought its own problem: a replacement node had no data. Downloading the 24 TB from S3 with s5cmd took 3 hours; copying from a healthy node in the same datacenter with fpsync took 1.5 hours. The team then kept a spare node with the dataset preloaded in the Slurm reservation, so a failed node could be swapped at once; the spare ran evaluations or development jobs while idle.\n\nThe drops that remained came from the dataloader. SmolLM2 had been trained with steady throughput on a Megatron-LM-derived dataloader, TokenizedBytes, but SmolLM3 used nanotron's built-in dataloader, nanosets, which the team had never used for large-scale pretraining. nanosets built a single large index that grew with every training step, and at very large step counts the higher shared memory use caused the throughput drops. The same configuration run with TokenizedBytes in the team's internal SmolLM2 framework showed no drops on 48 nodes, so the team copied TokenizedBytes into nanotron instead of fixing the nanosets index, and throughput returned to target. TokenizedBytes read sequences in order within each document and made the loss noisier, which the team fixed by pre-shuffling the tokenized sequences offline for each epoch before relaunching.","ko":"Hugging Face 는 고정 Slurm 예약으로 잡은 48개 노드의 H100 GPU 384개에서 SmolLM3 를 한 달 가까이 학습했다. 본 학습 직전에 같은 48개 노드에서 처리량 검증을 마쳤지만, 시작하고 몇 시간 만에 처리량이 크게 떨어졌다. 서로 다른 원인 두 가지가 겹쳐 있었다.\n\n첫째 원인은 스토리지였다. 팀은 24 TB 데이터셋을 /fsx 에 마운트된 WekaFS 에 두었다. Weka 는 자주 읽는 파일을 로컬에 두고, 용량이 차면 오래 읽지 않은 파일을 S3 로 내보내는 방식으로 동작한다. 여러 팀이 이미 쓰고 있던 용량에 24 TB 가 더해지자 Weka 가 한계에 닿았다. Weka 는 학습 도중 데이터셋 샤드를 내보내기 시작했다. 내보낸 샤드를 다시 가져오는 동안 학습이 멈췄고, 그래서 처리량이 크게 떨어졌다. 팀은 데이터셋 폴더를 학습 내내 자주 읽는 상태로 고정할 방법을 찾지 못했다. S3 에서 바로 스트리밍하는 방식은 느렸다. 그래서 데이터를 각 노드의 로컬 NVMe RAID 스크래치 스토리지에 두었다. 이 방식에는 노드가 죽어 교체되면 새 노드에 데이터가 없다는 문제가 있었다. 팀은 데이터셋을 미리 올린 예비 노드를 두어 이 문제를 풀었다.\n\n둘째 원인은 데이터로더였다. SmolLM2 는 Megatron-LM 에서 가져온 TokenizedBytes 데이터로더로 안정된 처리량을 냈다. SmolLM3 에서는 Nanotron 에 내장된 nanosets 데이터로더로 바꿨다. 팀은 이 데이터로더로 대규모 사전 학습을 해 본 적이 없었다. nanosets 는 학습 스텝마다 커지는 거대한 인덱스 하나를 단순한 방식으로 만들고 있었다. 스텝 수가 아주 크면 공유 메모리 사용량이 늘었고, 그 때문에 처리량이 급락했다. 팀은 내부 SmolLM2 프레임워크에서 TokenizedBytes 로 같은 설정을 돌려, 48개 노드에서 급락이 없다는 것을 확인했다. 그다음 이 데이터로더를 Nanotron 에 복사해 넣었다. 새 데이터로더는 문서 안의 시퀀스를 차례대로 읽었고, 그 탓에 손실 곡선이 거칠어졌다. 팀은 시퀀스를 오프라인에서 미리 섞은 뒤 학습을 다시 시작했다. 이번에는 처리량이 일정하게 유지됐다."},"trigger":{"en":"Launching the full run with the whole ~24 TB dataset on shared WekaFS storage and the real step count for 11T tokens, both far larger than in the ablation runs.","ko":"팀은 약 24 TB 전체 데이터셋을 여러 팀이 함께 쓰는 Weka 스토리지에 두고, 11T 토큰에 맞춘 실제 스텝 수로 본 학습을 시작했다."},"severity":"unknown","symptoms":["throughput-degraded"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":{"en":"The team watched training throughput in tokens per second and saw it fall within hours of launch; node-monitoring metrics then tied the large fall to spikes in disk read latency.","ko":"팀은 학습 중 초당 토큰 처리량을 기록하고 있었다. 학습을 시작하고 몇 시간 안에 이 값이 급락하는 것이 보였다. SmolLM3 에서 기대한 처리량은 초당 13,500에서 14,000 토큰이었다. 팀은 처리량이 이 범위를 계속 벗어나면 위험 신호로 보았다. 그리고 노드 모니터링 지표에서 처리량이 떨어진 시점과 디스크 읽기 지연이 급증한 시점이 겹치는 것을 보고 스토리지를 원인으로 짚었다."},"components":["shared-filesystem","training-dataloader"],"root_cause":"capacity","remediation":[{"text":{"en":"moved the training data from WekaFS to the local NVMe RAID scratch storage on each node","ko":"데이터셋을 Weka 에서 빼서 각 노드의 로컬 NVMe RAID 스크래치 스토리지에 올렸다."}},{"text":{"en":"copied the dataset to replacement nodes from a healthy node with fpsync, cutting the copy from 3 hours to 1.5 hours","ko":"교체한 노드에 데이터를 채울 때 S3 에서 s5cmd 로 24 TB 를 받으면 3시간이 걸렸다. 그래서 같은 데이터센터의 정상 노드에서 fpsync 로 복사해 1.5시간으로 줄였다."}},{"text":{"en":"kept a spare node with the dataset preloaded in the Slurm reservation to swap in when a node failed","ko":"데이터셋을 미리 올려 둔 예비 노드 하나를 Slurm 예약에 넣어 두고, 노드가 죽으면 바로 예비 노드로 바꿨다."}},{"text":{"en":"reproduced the drops on a single node and with step counts of about 3M and 32k to rule out hardware and isolate the step count","ko":"노드 하나에서도 급락을 재현해 하드웨어를 원인에서 뺐고, 약 3M 스텝과 32k 스텝으로 각각 돌려 원인을 스텝 수로 좁혔다."}},{"text":{"en":"replaced nanotron's nanosets dataloader with the TokenizedBytes dataloader copied from the SmolLM2 setup, which removed the drops","ko":"Nanotron 의 nanosets 데이터로더를 SmolLM2 에서 쓰던 TokenizedBytes 데이터로더로 바꿔 넣자 급락이 사라졌다."}},{"text":{"en":"pre-shuffled the tokenized sequences offline for each epoch with different seeds (about 1 hour) to fix the noisier loss from TokenizedBytes","ko":"TokenizedBytes 로 바꾼 뒤 손실이 거칠어진 문제를 고치려고, 토큰화된 시퀀스를 에포크마다 다른 시드로 오프라인에서 미리 섞었다. 이 작업에 약 1시간이 걸렸다."}}],"action_items":[],"contributing":["overlapping-failures","staging-not-representative","assumption-unverified"],"recurrence_of":null,"symptoms_text":{"en":"Within hours of launching the full SmolLM3 pretraining run (3B parameters, 11T tokens, 384 H100 GPUs on 48 nodes), training throughput fell steeply, with repeated sharp drops. The team expected a steady 13,500 to 14,000 tokens per second, and none of the throughput ablations run beforehand on the same 48 nodes had shown drops.\n\nOnly three things differed from the ablations: the run now read the full training dataset of about 24 TB instead of subsets, the step count was set for 11T tokens instead of a 100B-token horizon, and the state of the hardware might have changed under sustained load. Hardware was the first suspect. Node-monitoring metrics showed that the large throughput fall lined up with spikes in disk read latency, which pointed at the data storage: the dataset sat on the shared WekaFS filesystem mounted at /fsx.\n\nAfter the data was moved to each node's local NVMe RAID, the individual drops continued and became sharper, while hardware monitoring showed nothing unusual. The same drops appeared on a single node, whichever node was used, which ruled out hardware. Cutting the step count from about 3M to 32k made the drops smaller; longer step counts produced sharper and more frequent drops.","ko":"Hugging Face 팀은 SmolLM3 본 학습을 시작했다. 48개 노드의 H100 GPU 384개로 11T 토큰을 학습하는 일정이었다. 시작하고 몇 시간 안에 처리량이 가파르게 떨어졌고, 이런 급락이 여러 번 되풀이됐다. 처리량은 학습 중 초당 처리하는 토큰 수다. 처리량이 50% 떨어지면 한 달짜리 학습이 두 달짜리가 된다.\n\n같은 48개 노드에서 미리 돌린 처리량 어블레이션 실험에서는 이런 일이 없었다. 어블레이션은 구성 요소 하나씩을 바꿔 가며 영향을 재는 작은 실험이다. 본 학습에서 바뀐 것은 셋이었다. 첫째, 데이터셋이 작은 부분집합에서 약 24 TB 전체로 커졌다. 둘째, 학습 스텝 수가 100B 토큰 실험 길이에서 11T 토큰에 맞는 실제 값으로 늘었다. 셋째, 오래 부하를 받은 하드웨어의 상태가 달라졌을 수 있었다. 노드 수, 데이터로더 설정, 모델 레이아웃, 병렬화 설정은 그대로였다.\n\n팀은 데이터셋 크기나 스텝 수가 처리량을 떨어뜨릴 리 없다고 보고 먼저 하드웨어를 의심했다. 노드 모니터링 지표를 보니 처리량이 크게 떨어진 시점과 디스크 읽기 지연이 급증한 시점이 겹쳤다. 팀은 데이터 스토리지를 살폈고, Weka 가 학습 도중 데이터셋 샤드를 S3 로 내보내고 있다는 것을 알아냈다.\n\n데이터를 각 노드의 로컬 NVMe 로 옮긴 뒤에도 급락은 한 번씩 계속 나타났다. 이번에는 하드웨어 모니터링 지표에 이상이 없었다. 어블레이션 때와 비교하면 급락은 오히려 훨씬 가팔라졌다. 팀은 여전히 하드웨어를 의심해 노드 수를 줄여 가며 시험했다. 그러자 어느 노드를 고르든 노드 하나만으로도 똑같은 급락이 재현됐다. 하드웨어가 원인에서 빠지자 남은 변수는 스텝 수였다. 스텝 수를 3M 에서 32k 로 줄이자 급락이 작아졌다. 스텝 수가 클수록 급락은 더 가파르고 잦았다."},"updated_at":"2026-11-09T11:55:49.267715Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0129","org_slug":"hugging-face"}