66import os
77import tempfile
88from dataclasses import dataclass
9+ from math import gcd
910from typing import Any , Dict , Optional , Tuple
1011
1112import torch
2829PAD_TOKEN_ID = 151643
2930
3031
31- def seq_padding_for_cp (data , tp_size = 1 , cp_size = 1 , has_sp = False ):
32+ def _lcm (lhs , rhs ):
33+ return lhs * rhs // gcd (lhs , rhs )
34+
35+
36+ def _sequence_padding_factor (tp_size = 1 , cp_size = 1 , has_sp = False ):
37+ if has_sp and cp_size > 1 :
38+ return tp_size * cp_size * 2
39+ if cp_size > 1 :
40+ return cp_size * 2
41+ if has_sp :
42+ return tp_size
43+ return 1
44+
45+
46+ def _fp8_padding_factor (fp8_recipe = None ):
47+ if fp8_recipe == "mxfp8" :
48+ return 32
49+ if fp8_recipe == "blockwise" :
50+ return 128
51+ return 16
52+
53+
54+ def _needs_packed_alignment (args ):
55+ return args .packing_sft_data and (
56+ args .context_parallel_size > 1
57+ or args .sequence_parallel
58+ or (
59+ bool (getattr (args , "fp8" , None ))
60+ and getattr (args , "fp8_recipe" , None ) == "blockwise"
61+ )
62+ )
63+
64+
65+ def seq_padding_for_cp (
66+ data ,
67+ tp_size = 1 ,
68+ cp_size = 1 ,
69+ has_sp = False ,
70+ fp8_enabled = False ,
71+ fp8_recipe = None ,
72+ ):
3273 """Sequence padding for CP and/or SP
3374
3475 Args:
3576 data (dict): Data from dataloader.
3677 tp_size (int): Tensor parallel size.
3778 cp_size (int): Context parallel size.
3879 has_sp (bool): Model uses sequence parallelism.
80+ fp8_enabled (bool): Model uses FP8 execution.
81+ fp8_recipe (str): FP8 recipe. Affects required padding.
3982
4083 Returns:
4184 data (dict): Padded data.
@@ -54,6 +97,7 @@ def seq_padding_for_cp(data, tp_size=1, cp_size=1, has_sp=False):
5497 seq_lengths = cu_lengths [0 , 1 :] - cu_lengths [0 , :- 1 ]
5598 start = 0
5699 for length in seq_lengths :
100+ length = int (length )
57101 token = tokens [0 , start : start + length ]
58102 label = labels [0 , start : start + length ]
59103 mask = attn_mask [0 , start : start + length ]
@@ -76,11 +120,37 @@ def seq_padding_for_cp(data, tp_size=1, cp_size=1, has_sp=False):
76120
77121 start += length
78122
123+ final_padding_factor = _sequence_padding_factor (tp_size , cp_size , has_sp )
124+ if fp8_enabled :
125+ fp8_padding_factor = _fp8_padding_factor (fp8_recipe )
126+ if has_sp :
127+ fp8_padding_factor *= tp_size
128+ final_padding_factor = _lcm (final_padding_factor , fp8_padding_factor )
129+
130+ final_padding_needed = (
131+ int (
132+ (cu_seqlens_padded [- 1 ] + final_padding_factor - 1 )
133+ // final_padding_factor
134+ * final_padding_factor
135+ )
136+ - cu_seqlens_padded [- 1 ]
137+ )
138+
139+ if final_padding_needed > 0 and valid_tokens :
140+ valid_tokens [- 1 ] = F .pad (
141+ valid_tokens [- 1 ], (0 , final_padding_needed ), "constant" , PAD_TOKEN_ID
142+ )
143+ valid_labels [- 1 ] = F .pad (
144+ valid_labels [- 1 ], (0 , final_padding_needed ), "constant" , IGNORE_INDEX
145+ )
146+ valid_attn_mask [- 1 ] = F .pad (
147+ valid_attn_mask [- 1 ], (0 , final_padding_needed ), "constant" , True
148+ )
149+ cu_seqlens_padded [- 1 ] += final_padding_needed
150+
79151 data ["tokens" ] = torch .cat (valid_tokens , dim = 0 ).unsqueeze (0 ).to (tokens .dtype )
80152 data ["labels" ] = torch .cat (valid_labels , dim = 0 ).unsqueeze (0 ).to (labels .dtype )
81- data ["attn_mask" ] = (
82- torch .cat (valid_attn_mask , dim = 0 ).unsqueeze (0 ).to (attn_mask .dtype )
83- )
153+ data ["attn_mask" ] = torch .cat (valid_attn_mask , dim = 0 ).unsqueeze (0 ).to (attn_mask .dtype )
84154
85155 data ["cu_lengths" ] = torch .tensor (
86156 cu_seqlens_padded , dtype = cu_lengths .dtype
@@ -111,14 +181,14 @@ def collate_energon(self, batch: Dict[str, Any]) -> Dict[str, Any]:
111181 batch = self ._ensure_tensor (batch )
112182 self ._pad_sequences (batch )
113183 args = get_args ()
114- if args .packing_sft_data and (
115- args .context_parallel_size > 1 or args .sequence_parallel
116- ):
184+ if _needs_packed_alignment (args ):
117185 seq_padding_for_cp (
118186 batch ,
119187 tp_size = args .tensor_model_parallel_size ,
120188 cp_size = args .context_parallel_size ,
121189 has_sp = args .sequence_parallel ,
190+ fp8_enabled = bool (getattr (args , "fp8" , None )),
191+ fp8_recipe = getattr (args , "fp8_recipe" , None ),
122192 )
123193 self ._build_masks_and_positions (batch )
124194 return batch
0 commit comments