|
33 | 33 | from megatron.core.tensor_parallel.mappings import ( |
34 | 34 | gather_from_sequence_parallel_region, |
35 | 35 | gather_from_tensor_model_parallel_region, |
36 | | - reduce_from_tensor_model_parallel_region, |
37 | 36 | scatter_to_sequence_parallel_region, |
38 | 37 | ) |
39 | 38 | from megatron.core.transformer.attention import Attention, LinearProjBuilder |
|
73 | 72 | mxfp8_quantize_only, |
74 | 73 | mxfp8_transpose_swizzle, |
75 | 74 | ) |
76 | | - from transformer_engine.pytorch.cpp_extensions import general_gemm |
77 | 75 | from transformer_engine.pytorch.quantized_tensor import QuantizedTensor |
78 | 76 | from transformer_engine.pytorch.tensor.mxfp8_tensor import MXFP8Quantizer |
79 | 77 |
|
|
99 | 97 | FusedMLAQUpProjRopeQuant, |
100 | 98 | mxfp8_quantize_only, |
101 | 99 | mxfp8_transpose_swizzle, |
102 | | - general_gemm, |
103 | 100 | QuantizedTensor, |
104 | 101 | MXFP8Quantizer, |
105 | 102 | ) = (None, None, None, None, None, None, None, None, None, None, None, None, None, None) |
@@ -187,105 +184,18 @@ def backward(ctx, dq): |
187 | 184 | # grad w.r.t. the (pre-RoPE) up-proj GEMM output; bf16. |
188 | 185 | dq2d = dq3.reshape(tokens, nh * q_head_dim).contiguous() |
189 | 186 |
|
190 | | - # Dispatch the adjoints on the projection precision (== forward kernel), inferred from w_q: |
191 | | - # QuantizedTensor -> fp8 projection (mxfp8in); plain bf16 tensor |
192 | | - # -> 16-bit projection (bf16in). |
193 | | - if isinstance(w_q, QuantizedTensor): |
194 | | - # FP8 projection: fp8 adjoints via TE general_gemm |
195 | | - # x_saved is the columnwise MXFP8 activation |
196 | | - # split_accumulator=True matches the MXFP8 recipe default for grad GEMMs. |
197 | | - grad_output_quantizer = MXFP8Quantizer( |
198 | | - fp8_dtype=tex.DType.kFloat8E4M3, rowwise=True, columnwise=True |
199 | | - ) |
200 | | - # Pre-swizzle the grad-output scales at cast time, so general_gemm's in-GEMM swizzle |
201 | | - # is a no-op (avoids the extra cast_only + standalone row/col swizzle). Layout only, |
202 | | - # no effect on numerics. |
203 | | - grad_output_quantizer.optimize_for_gemm = True |
204 | | - gy = grad_output_quantizer(dq2d) # MXFP8: rowwise (dgrad) + columnwise (wgrad) |
205 | | - |
206 | | - w_q.update_usage(rowwise_usage=True, columnwise_usage=True) |
207 | | - |
208 | | - # dgrad: grad_input = grad_output @ weight |
209 | | - # (A=weight[colwise], B=grad_output[rowwise], NN) |
210 | | - grad_x = general_gemm( |
211 | | - w_q, gy, layout="NN", grad=True, out_dtype=act_dtype, use_split_accumulator=True |
212 | | - )[0].reshape(s, b, -1) |
213 | | - |
214 | | - # wgrad: grad_weight = grad_output^T @ input |
215 | | - # (A=input[colwise], B=grad_output[colwise], NT) |
216 | | - if ctx.wgrad_store is not None and ctx.wgrad_store.delay_wgrad_compute(): |
217 | | - if ctx.fuse_wgrad_accumulation and hasattr(w_q, "main_grad"): |
218 | | - |
219 | | - def _wgrad(x_, gy_): |
220 | | - # Accumulate the fp8 wgrad directly into fp32 main_grad (out=main_grad, |
221 | | - # accumulate=True), exactly as TE's fused-wgrad path does. |
222 | | - general_gemm( |
223 | | - x_, |
224 | | - gy_, |
225 | | - layout="NT", |
226 | | - grad=True, |
227 | | - out=w_q.main_grad, |
228 | | - out_dtype=w_q.main_grad.dtype, |
229 | | - accumulate=True, |
230 | | - use_split_accumulator=True, |
231 | | - ) |
232 | | - return w_q.main_grad, None |
233 | | - |
234 | | - ctx.wgrad_store.put([x_saved, gy], _wgrad) |
235 | | - if hasattr(w_q, "grad_added_to_main_grad"): |
236 | | - w_q.grad_added_to_main_grad = True |
237 | | - ret_grad_w = torch.empty_like(w_q) # dummy; discarded by the reduce hook |
238 | | - else: |
239 | | - ctx.wgrad_store.put( |
240 | | - [x_saved, gy], |
241 | | - lambda x_, gy_: ( |
242 | | - general_gemm( |
243 | | - x_, |
244 | | - gy_, |
245 | | - layout="NT", |
246 | | - grad=True, |
247 | | - out_dtype=act_dtype, |
248 | | - use_split_accumulator=True, |
249 | | - )[0], |
250 | | - None, |
251 | | - ), |
252 | | - ) |
253 | | - ret_grad_w = None |
254 | | - else: |
255 | | - ret_grad_w = general_gemm( |
256 | | - x_saved, |
257 | | - gy, |
258 | | - layout="NT", |
259 | | - grad=True, |
260 | | - out_dtype=act_dtype, |
261 | | - use_split_accumulator=True, |
262 | | - )[0] |
263 | | - else: |
264 | | - # === 16-bit projection: bf16 adjoints, matching the unfused bf16 up-proj backward. |
265 | | - # x_saved and w_q are bf16. === |
266 | | - grad_x = (dq2d @ w_q).reshape(s, b, -1) # [s, b, q_lora], bf16 |
267 | | - |
268 | | - if ctx.wgrad_store is not None and ctx.wgrad_store.delay_wgrad_compute(): |
269 | | - if ctx.fuse_wgrad_accumulation and hasattr(w_q, "main_grad"): |
270 | | - |
271 | | - def _wgrad(dq2d_, x_): |
272 | | - w_q.main_grad.add_( |
273 | | - (dq2d_.t() @ x_).to(w_q.main_grad.dtype).reshape(w_q.main_grad.shape) |
274 | | - ) |
275 | | - return w_q.main_grad, None |
276 | | - |
277 | | - ctx.wgrad_store.put([dq2d, x_saved], _wgrad) |
278 | | - if hasattr(w_q, "grad_added_to_main_grad"): |
279 | | - w_q.grad_added_to_main_grad = True |
280 | | - ret_grad_w = torch.empty_like(w_q) # dummy; discarded by the reduce hook |
281 | | - else: |
282 | | - ctx.wgrad_store.put([dq2d, x_saved], lambda dq_, x_: (dq_.t() @ x_, None)) |
283 | | - ret_grad_w = None |
284 | | - else: |
285 | | - ret_grad_w = dq2d.t() @ x_saved # [nh*q_head_dim, q_lora], bf16 |
286 | | - |
287 | | - if get_pg_size(ctx.tp_group) > 1 and not ctx.sequence_parallel: |
288 | | - grad_x = reduce_from_tensor_model_parallel_region(grad_x, group=ctx.tp_group) |
| 187 | + # Delegate the projection backward to TE's _linear_backward (via backward_linear) |
| 188 | + grad_x, ret_grad_w = FusedMLAQUpProjRopeQuant.backward_linear( |
| 189 | + grad_output=dq2d, |
| 190 | + x_saved=x_saved, |
| 191 | + w_q=w_q, |
| 192 | + act_dtype=act_dtype, |
| 193 | + wgrad_store=ctx.wgrad_store, |
| 194 | + fuse_wgrad_accumulation=ctx.fuse_wgrad_accumulation, |
| 195 | + tp_group=ctx.tp_group, |
| 196 | + sequence_parallel=ctx.sequence_parallel, |
| 197 | + ) |
| 198 | + grad_x = grad_x.reshape(s, b, -1) |
289 | 199 |
|
290 | 200 | # grads for: q_normed, w_q, cos, sin, then 10 non-tensor args |
291 | 201 | # (including tp_group, sequence_parallel) |
|
0 commit comments