PyTorch DDP多卡训练:从跑通到跑快的三步

举报
yd_264617019 发表于 2026/11/13 11:35:05 2026/11/13
【摘要】 第一次把微调任务从单卡迁到4卡DDP,踩了一串坑。从"能跑"到"线性加速"中间隔着三步,记录完整过程。第一步,跑通。DDP的基本结构:torchrun启动多进程,每个进程持有一份模型副本,DistributedSampler保证各卡数据不重叠,反向传播时梯度自动all-reduce同步。最常见的报错是没设rank判断就所有进程都写checkpoint和打日志,磁盘和日志直接打架,所有IO操作...

第一次把微调任务从单卡迁到4卡DDP,踩了一串坑。从"能跑"到"线性加速"中间隔着三步,记录完整过程。

第一步,跑通。DDP的基本结构:torchrun启动多进程,每个进程持有一份模型副本,DistributedSampler保证各卡数据不重叠,反向传播时梯度自动all-reduce同步。最常见的报错是没设rank判断就所有进程都写checkpoint和打日志,磁盘和日志直接打架,所有IO操作包一层if rank等于0。

第二步,消灭数据倾斜。DistributedSampler自动做数据分片,但它默认pad_to_multiple_of会把数据集补齐到卡数的整数倍,小数据集时重复样本被训练两次,验证指标莫名虚高。shuffle也要靠sampler自带,自己再套DataLoader的shuffle会破坏分片语义。

第三步,性能压榨。起初四卡只有2.3倍加速,排查出三个损耗点。一是梯度同步和计算没有重叠,DDP默认在backward时同步,把小batch的通信占比放大,开梯度累积到等效大batch后通信摊薄;二是每步都调用dist.barrier做同步,纯属多余,删掉;三是各卡负载不均,长短句混排导致某张卡永远最慢,先按长度排序再分桶,配合bucket sampler均衡每步耗时。

sampler = DistributedSampler(dataset, shuffle=True)
loader = DataLoader(dataset, batch_size=32,
                    sampler=sampler, num_workers=8,
                    pin_memory=True)
for epoch in range(epochs):
    sampler.set_epoch(epoch)     # 保证每轮洗牌不同
    for batch in loader:
        loss = model(batch).loss / grad_accum
        loss.backward()
        if step % grad_accum == 0:
            optimizer.step(); optimizer.zero_grad()

三步之后,四卡加速比3.7,基本贴着线性上限。最后提醒一句:验证阶段要用all_gather把各卡的结果聚合再算指标,各自算完取平均在加权指标上是错的,这个隐蔽bug我们上线前一周才发现。

DDP的验证清单再补几条,都是血泪换的。一是确定性检查,固定seed后两次训练的loss曲线应该逐step一致,不一致多半有未被DDP同步的随机性,比如某处用了未加种子的numpy随机,这种问题不影响收敛但影响实验可比性。二是梯度范数监控,DDP下各卡的梯度是all-reduce后的均值,范数应该一致,如果打印各卡本地范数差异巨大,说明数据分片不均匀。三是save和load的map_location,checkpoint在rank0保存后,加载时所有卡都要加载到各自设备,显式指定而不是让框架猜。最后,遇到诡异的多进程挂死,先用py-spy dump看各进程栈,九成是某个rank提前抛异常退出,其他rank在通信点傻等,日志里的第一张报错卡才是真凶。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。