Repository navigation
fix(vocab_parallel_ce): take label smoothing from the summed shifted logits - #1619
Open
bhargavchintam wants to merge 1 commit into
Open
bhargavchintam wants to merge 1 commit into
bhargavchintam wants to merge 1 commit into
Conversation
…logits With label smoothing, the forward took log(exp(x - max)) over the whole [BT, V_local] buffer in Python. exp(x - max) underflows to 0 in fp32 once a logit is about 104 below the row max, so the loss came out as inf where F.cross_entropy is finite. The gradient was not affected. The forward kernel now also sums the shifted logits, and the smoothing term is sum(x - max) / K - log(sum_exp). This needs no [BT, V_local] temporaries, and ignored rows no longer have to be filled with ones.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1618
Summary
With
label_smoothing > 0,LigerVocabParallelCEFunction.forwardtooktorch.log(exp_buf)over the whole[BT, V_local]buffer to get the log-probabilities.exp(x - max)is 0 in fp32 once a logit is about 104 below the row max, so the loss came out asinfwhereF.cross_entropyis finite. The same line made two[BT, V_local]fp32 temporaries.Since
log_softmax_i = (x_i - max) - log(sum_exp), its mean over K classes issum_i(x_i - max) / K - log(sum_exp). With label smoothing on, the forward kernel now also sums the shifted logits per row (sum_shifted_ptr,Noneotherwise), and the smoothing term is taken from that sum. In "global" mode the AllReduce carries this sum instead of the summed log-probabilities; "partition" mode uses the local sum. Ignored rows no longer need theirexp_bufrow filled with ones, so that loop is removed.The diff is this change in
ops/vocab_parallel_cross_entropy.py(the forward kernel, the smoothing block, docstrings), one docstring line intransformers/vocab_parallel_cross_entropy.py, and the test below. The loss line, the backward kernel and the path without label smoothing are not changed.Details
#1555 also adds an output to this forward kernel, so I placed my lines where the two do not overlap. A merge of this branch with #1555's head (
2e68201) is clean in this file and in its test file. The one conflict is in a file this PR does not touch:#1331 wraps the kernel launch in
device_context, which re-indents the lines this PR edits there, so those two conflict in this file:Megatron-LM's own loss takes
torch.log(exp_logits)at this step (megatron/core/ops/loss/cross_entropy.py). I read that in its source and did not run it. If it behaves as written,LigerMegatronCrossEntropynow differs from it in these cases: a finite loss instead ofinf.Testing Done
make testto ensure correctness (68 failed, 5337 passed; the same 68 fail on main on this machine, shown below)make checkstyleto ensure code style (I ran its two check-only steps, shown at the end, because the other two steps rewrite files)make test-convergenceto ensure convergenceI did not run
make test-convergence.New test
test_label_smoothing_with_logits_far_below_the_max: both classes, 64 of 512 logits moved 120 or 1e4 below the rest, fp32 and bf16, a quarter of the rows ignored. The loss must be finite and matchF.cross_entropy, and so must the gradient.The whole file, on two GPUs so that the TP=2 cases run:
The snippet from the issue, saved as
issue_snippet.py, on this branch (on main it prints the values in the issue):Two ranks on two GPUs over NCCL, with my own script (not in this PR): three inputs (ordinary logits, low logits on one rank, low logits on both), both formulas, both modes,
label_smoothing0 and 0.1, each rank compared with an fp64log_softmaxreference. It checks the forward value in "partition" mode too.The 4-GPU and 8-GPU cases of the repo's test did not run on this machine (the 32 skips above). The same script with 4 and with 8 CPU ranks over gloo, under the Triton interpreter:
Memory and time at TP=1 on one L40S, main -> this PR, from my own script (not in this PR). "peak fwd MB" is what one forward allocates above its inputs; times are the median of 30 calls after 10 warm-up calls.
make teston this branch. None of the 68 failures is intest/megatron/. They are in ten other files:test_grpo_loss.py(24),test_mlp.py(18),test_fused_linear_score_centering.py(10),test_fused_neighborhood_attention.py(6),test_swiglu.py(3),test_rms_norm.py(2),test_flex_attention.py(2), and one each intest_muse_glimmer.py,test_geglu.pyandtest_fused_linear_selected_log_probs.py. I re-ran those 68 ids on main (42dc23c) and on this branch. The same 68 fail on both, and the two outputs are identical apart from the timing. I did not look into why they fail on an L40S.