Skip to content

Commit a3c8a5a

Browse files
author
mhh111
committed
[v1] shorten grad_norm fix comment
1 parent 6b7bb2b commit a3c8a5a

1 file changed

Lines changed: 7 additions & 18 deletions

File tree

src/llamafactory/v1/core/base_trainer.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -279,30 +279,19 @@ def fit(self) -> None:
279279
# deepspeed: engine.step() already ran inside backward at the sync boundary
280280
grad_norm = self._deepspeed_engine.get_grad_norm()
281281
else:
282-
# FSDP2 shards params/grads as DTensors across the fsdp mesh, so each rank only
283-
# holds 1/shard_size of every parameter. `get_total_norm`/`clip_grad_norm_`
284-
# return a *per-rank local shard* norm and `.item()` reads only that local
285-
# partial (== global_norm / sqrt(shard_size)). Using it directly makes the
286-
# reported grad_norm scale as 1/sqrt(dp_size) (e.g. 8xdp mbs1 vs 4xdp mbs2
287-
# differ by sqrt(2)), and -- worse -- makes `clip_grad_norm_` apply the clip
288-
# coefficient per-shard, corrupting the update once clipping is actually on.
289-
# Fix: reduce to the true global norm first (full_tensor all-reduces across the
290-
# fsdp shard mesh), then clip with that scalar via clip_grads_with_norm_.
282+
# FSDP2 shards params/grads across the fsdp mesh, so clip_grad_norm_ returns a
283+
# per-rank local shard norm (global / sqrt(shard_size)): reported grad_norm then
284+
# scales as 1/sqrt(dp_size) and the clip coefficient is applied per-shard. Reduce
285+
# to the true global norm first, then clip with it.
291286
from torch.distributed.tensor import DTensor
292287

293288
grads = [p.grad for p in self.model.parameters() if p.grad is not None]
294289
total_norm = torch.nn.utils.get_total_norm(grads)
295290
if isinstance(total_norm, DTensor):
296-
# full_tensor already all-reduces across the whole fsdp shard mesh. With the
297-
# default mp_shard_size = world_size this mesh spans CP too, so FSDP's
298-
# reduce-scatter has already summed grads across CP -- no separate CP
299-
# reduction is wanted (it would over-count grad_norm by sqrt(cp_size) and
300-
# also skew the clip coefficient below). CP-on and CP-off both report the
301-
# true global norm this way.
291+
# full_tensor all-reduces across the fsdp mesh (spans CP under default
292+
# mp_shard=world); a separate CP reduce would over-count by sqrt(cp_size).
302293
total_norm = total_norm.full_tensor()
303-
# pass the (replicated) global norm as a Tensor -- clip_grads_with_norm_ does
304-
# torch.clamp(max_norm / (total_norm + 1e-6), max=1.0), which rejects a bare
305-
# python float. .item() for reporting only, after clipping.
294+
# pass a Tensor: clip_grads_with_norm_ clamps max_norm / (total_norm + 1e-6).
306295
torch.nn.utils.clip_grads_with_norm_(
307296
self.model.parameters(), self.args.max_grad_norm, total_norm
308297
)

0 commit comments

Comments
 (0)