If you have single-GPU model replica + DDP, will it be acceptable to let DDP first do gradient averaging, and then do gradient scaling/clipping independently on every process before calling optimizer.step(). Since DDP will make sure that all model replicas have the same gradient, their should reach the same scaling/clipping result.
Another thing is that, to accumulate gradients from multiple iterations, you can try using the ddp.no_sync() 24, which can help avoid unnecessary communication overheads.