Make packed sequence alignment FP8-safe#1828
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the sequence alignment and padding logic in Megatron utilities and dataset collators to support Transformer Engine FP8 GEMM requirements, ensuring that local token slabs are 16-aligned. The feedback suggests refactoring the duplicated alignment helper function _get_packed_seq_align_size into a single public utility to prevent code duplication and potential logic drift across the codebase and tests.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
3b1355f to
341fa91
Compare
erictang000
left a comment
There was a problem hiding this comment.
PR looks good, just 1 comment
| layout_align = tp_size * cp_size * 2 | ||
| else: | ||
| layout_align = tp_size | ||
| return math.lcm(layout_align, 16 * cp_size) |
There was a problem hiding this comment.
is it possible to only do 16 alignment if fp8 is enabled? here in the worker we can likely access the megatron model config to check if fp8 is enabled, and in collators.py, we should just pass through megatron_config.transformer_config_kwargs["fp8"] to see if it's enabled and we need to pad subsequences to 16*cp_size.
otherwise we will do unnecessary padding for the bf16 case, which could create additional memory pressure, especially when we have cp_size > 1
341fa91 to
0321c44
Compare
SkyRL FP8-Safe Sequence Alignment PR
Summary
This PR fixes Transformer Engine FP8 failures caused by sequence lengths that are valid for SkyRL/Megatron TP or CP layout, but invalid for TE FP8 GEMMs.
Main currently pads sequence lengths only to satisfy Megatron layout constraints:
remove_left_padding: pad totp_sizewhentp_size > 1;preprocess_packed_seqs: pad each subsequence totp_size, ortp_size * cp_size * 2when CP is enabled.That is not enough for FP8. TE/cublasLt FP8 GEMMs require the local token dimension used by each rank to be 16-aligned. Without this, FP8 forward/backward can fail with:
For CP, the subtle part is that
preprocess_packed_seqspads the global subsequence length and then shards it bycp_size. So aligning the global length to 16 is not sufficient: afterglobal_len // cp_size, the local CP-rank slab can still be 8, 4, 2, etc.Root Cause
There are two failure modes.
TP-only or CP-disabled path:
Example:
tp=8, cp=1Main can emit token lengths such as
8or24. These are divisible by TP, but not valid for the cublasLt FP8 leading-dimension requirement.Packed CP path:
Example:
tp=2, cp=2Main pads a raw length of
8to global length8, then CP shards it:That local length is invalid for TE FP8.
Example:
tp=1, cp=4Also invalid.
Fix
The PR makes packed sequence alignment satisfy both Megatron layout constraints and TE FP8 local-rank constraints.
For packed sequences:
Why
16 * cp_size:global_padded_length // cp_size.16 * cp_size.For non-packed left-padding removal:
remove_left_paddingalready assertscp_size == 1, so no CP multiplier is needed there.The same packed alignment formula is applied in both places that must stay in lockstep:
skyrl/backends/skyrl_train/distributed/megatron/megatron_utils.pyskyrl/train/dataset/collators.pyThis keeps controller-side packed row offsets and worker-side
preprocess_packed_seqsoffsets identical.H100 Verification
The verification used
remove_left_paddingandpreprocess_packed_seqsoutputs, then fed those resulting local token lengths into a TE FP8Linearforward/backward.Upstream Main Fails
Results:
Patched Branch Passes
Results:
Unit Tests
Why This Fix Covers All Observed Failures
The observed FP8 failures all reduce to one invariant:
For
cp=1, local length equals the padded sequence length, solcm(tp_size, 16)is enough.For packed
cp>1, local length equals:So the global packed subsequence length must be divisible by:
The patched packed formula:
simultaneously preserves: