Skip to content

Fuse the GSPO segment seam into compiled blocks (#507)#554

Open
jlamypoirier wants to merge 1 commit into
jlp_monolithic_head_lossfrom
jlp_gspo_seam_compile
Open

Fuse the GSPO segment seam into compiled blocks (#507)#554
jlamypoirier wants to merge 1 commit into
jlp_monolithic_head_lossfrom
jlp_gspo_seam_compile

Conversation

@jlamypoirier

Copy link
Copy Markdown
Collaborator

Authored by Claude Opus 4.8 (1M context), reviewed by @jlamypoirier.

Follow-up to the monolithic head-loss work (#507), stacked on #549.

What

gspo_segment_seam — the eager glue between GSPO's compiled forward and backward cores — ran ~13 small elementwise/gather/reduction ops as separate launches around the index_add_ segment aggregation. This splits the fusable work into two @torch.compile blocks:

  • pre-aggregation (_gspo_segment_weights): the per-token contributions feeding index_add_;
  • post-aggregation (_gspo_segment_loss): from the reduced per-segment sums to the loss, the new_logprobs metric, and the unscaled per-token backward coefficient.

The middle stays eager: the index_add_ (its symbolic num_segments would trigger per-value recompiles) and the SDP/SP all-reduces (comm). The per-step-varying / divisor and grad_output scaling also stay eager, so they never specialize the compiled graphs (epsilon_* are fixed per run, so they don't).

Both consumers of the seam benefit — standalone GSPO and the monolithic finish path — and the eventual Triton monolithic loss reuses the same seam.

Correctness

Numerically equivalent to the prior eager seam. Verified against the existing GSPO cases (the equivalence oracle): all test_gspo_loss / test_lm_head GSPO configs (standalone, masked, uneven-documents, fused-monolithic) and the distributed world_size=2 SDP/SP path pass. A serial run across varied segment counts shows no recompiles beyond the initial compile.

🤖 Generated with Claude Code

`gspo_segment_seam` ran ~13 small elementwise/gather/reduction ops as separate eager
launches around the `index_add_` aggregation. Split the fusable work into two
`@torch.compile` blocks — pre-aggregation per-token weights and post-aggregation
loss/gradient — around the eager `index_add_` + SDP/SP all-reduce middle, which stays
eager (the symbolic `num_segments` would trigger per-value recompiles, and the
all-reduces are comm). The per-step-varying `/ divisor` and `grad_output` scaling
stay eager too so they never specialize the compiled graphs.

Numerically equivalent to the prior eager seam across standalone GSPO, the monolithic
`finish` path, and the distributed SDP/SP path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant