这类问题我又碰上了一次。四卡训练时发现每个 epoch 的样本数几乎是数据集的两倍,日志里不同 rank 打印的样本 id 有大量重复。
第一反应是「dataloader 没有设置分布式采样」,验证下来不成立。
真正麻烦的地方在于,几个原因的现象几乎一样。用了普通采样器,每个 rank 都遍历全量数据;自定义采样器没有按 rank 切分索引;数据并行组初始化失败,rank 号全是零。
上来先改用分布式采样器
sampler = DistributedSampler(ds, num_replicas=world_size, rank=rank, shuffle=True)
每个 epoch 前设置采样器轮次
sampler.set_epoch(epoch)
然后确认每个 rank 拿到的索引不重叠
python -c "print(len(set(idx_rank0) & set(idx_rank1)))"
末了核对进程组初始化是否正确
print(dist.get_rank(), dist.get_world_size())
当时还开着另一个排查窗口,两边日志对照着看才定位到。
恢复的判定其实很直接。每个 epoch 遍历的样本数等于数据集大小,各 rank 索引互不重叠,训练轮次与预期一致。
样本重复不会报错,只会让模型多看了几遍数据,表现成训练集指标虚高而验证集不动,很不容易被发现。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。