[Loss] Split logging loss from backward loss#1962
Conversation
Restore every displayed loss scalar from a detached per-rank LOCAL component reduced across ranks with a SUM all_reduce, instead of mean-reducing the (globally reduced) backward loss tensors. Because each term's cross-rank SUM equals the global loss, the logged curves are unchanged while backward still uses the current global autograd path; this decouples display from backward so the reduce-sum switch can make backward per-rank-local without touching logs. - BalancingLossContext.finalize / ZLossContext now also produce a detached local component (z-loss's without the x world_size factor); MoE forward records them on extra_info as local_*loss (CE already exposes local_base_loss, MTP mirrored). - BaseModel.post_micro_batch_forward and train_step total_loss reduce these local components with detached SUM; train_step total_loss is now the global value. Behavior-neutral: EP=2, balancing+z on, grad-acc=2, symmetric data reproduces C1's total_loss / reduced_llm_loss / reduced_balancing_loss / reduced_z_loss bit-for-bit.
c216448 to
184b6ca
Compare
a13bca8 to
316b1cc
Compare
| loss = self._get_total_loss(output) | ||
| loss.backward() | ||
| total_loss += loss.detach() | ||
| local_display_loss += self.model.local_display_loss(output) |
There was a problem hiding this comment.
loss reduction, otherwise still do it in post_micro_batch_forward?
| local_z_loss = z_locals[0] if len(z_locals) == 1 else torch.stack(z_locals).sum(dim=0) | ||
|
|
||
| return balancing_loss, z_loss, tokens_per_expert_global | ||
| return balancing_loss, z_loss, tokens_per_expert_global, local_balancing_loss, local_z_loss |
There was a problem hiding this comment.
Return a TypedDict, as the tuple return type is not convenient for extension
| if dist.is_initialized(): | ||
| dist.all_reduce(local_display_loss, op=dist.ReduceOp.SUM) |
There was a problem hiding this comment.
This part of the logic is placed in post_micro_batch_forward, and I hope each rank can display its own loss without performing an all_reduce sum. Could you try multiplying this coefficient back instead of doing a global sum?
| loss = loss_vec.sum() * alpha / self._batch_size | ||
| local_loss = local_vec.sum() * alpha / self._batch_size | ||
| return loss, local_loss.detach() |
There was a problem hiding this comment.
Why return two losses? If a subsequent module needs to record it, just detach it there. Why implement it this way? The interfaces between modules are all very strange now
| non_pad_token=non_pad_token, | ||
| ) | ||
| balancing_loss, z_loss, tokens_per_expert_global = split_aux_output | ||
| balancing_loss, z_loss, tokens_per_expert_global, local_balancing_loss, local_z_loss = split_aux_output |
There was a problem hiding this comment.
If local_loss can be omitted, please simplify the interface
There was a problem hiding this comment.
I don't see the need to make so many changes just for printing loss
This PR (2/5) — behavior-neutral. Routes displayed/logged losses through detached per-rank local components reduced by cross-rank SUM; the backward loss is still globally reduced. Isolates the display pipeline so the next PR flips gradients without touching logging.
Full stack (merge bottom-up, under #1959):
reduce-sum-01-fsdp-helper— [FSDP] Add reduce-sum gradient reduction helperreduce-sum-02-split-logging— [Loss] Split logging loss from backward lossreduce-sum-03-switch-sum— [FSDP][Loss] Switch gradient reduction to SUMreduce-sum-04-remove-world-size— [Refactor] Remove unused world_size plumbingreduce-sum-05-drop-nonglobal— [Refactor] Drop non-global aux-loss averaging mode