这类问题我又碰上了一次。四卡训练时发现每个 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 索引互不重叠,训练轮次与预期一致。

样本重复不会报错,只会让模型多看了几遍数据,表现成训练集指标虚高而验证集不动,很不容易被发现。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189