[BUG] 在 ZeRO 阶段 0 中, get_global_grad_norm() 返回 None (fp32)
同 #7255 相同的症状(打开,没有相应的问题)。此处添加了一个问题、原因和修复,因此可以随意关闭一个作为另一个的重复。 描述问题 使用 fp32 训练在 ZeRO 阶段 0 中,并启用梯度裁剪,engine.get_global_grad_norm() 在 step() 之后返回 None。在阶段 1 中,相同的配置返回了范数。在 fp32 阶段 0 中,_take_model_step 中通过 clip_fp32_gradients() 进行梯度裁剪,该函数调用 deepspeed.runtime.utils.clip_grad_norm_。该函数返回总范数,但该值被丢弃(engine.py L3425-L3442)。之后,引擎只复制 optimizer._global_grad_norm。只有 fp16/bf16/ZeRO Wrapper 优化器设置了该属性。在 fp32 阶段 0 中,直接使用基本优化器(一个 torch.optim 优化器,或 DeepSpeed 的 FusedAdam、CPUAdam、FusedLamb 等),因此它保持为 None。在阶段 0 中使用 torch_autocast 也采用了相同的路径。这正是 #7255 所描述的内容:HF Trainer 将 max_grad_norm 映射为 gradient_clipping,在 max_grad_norm > 0 时从 get_global_grad_norm()(通过 Accelerate)读取范数,并在其日志中删除值为 None 的 grad_norm。由于 #8068 将 gradient_clipping 设置为默认值 1.0,因此纯粹的 DeepSpeed 配置也会遇到此问题。get_global_grad_norm() 的文档只列出了在 ZeRO-1/2 中,当禁用梯度范数计算时,返回 None,因此这看起来是意外的。 重现问题 1. 将其保存为 repro.py:
内容来源: deepspeedai/DeepSpeed