Skip to content

Commit d1e8b8b

Browse files
committed
[None][feat] Add MegaMoECuteDsl NVFP4 MoE backend
Add the MegaMoECuteDsl backend (ported swap-AB MoE kernel) with NVFP4 quantization for the PyTorch fused-MoE path, wired through ConfigurableMoE / create_moe and the cute_dsl_megamoe_nvfp4_blackwell custom op. Key points: - Per-expert NVFP4 scales (fc1_alpha / fc2_alpha / fc1_norm_const) threaded through the v2 kernel ABI, derived from each expert raw input scales. - FC1/FC2 weights are stored in the natural (slots, N, K_bytes) layout with K (hidden//2 / intermediate//2) innermost, and presented to the kernel as non-contiguous transpose(1, 2) views (slots, K_bytes, N) so the swap-AB kernel reads K-major with K stride-1. Materializing the transpose with .contiguous() would move K off the innermost axis and corrupt the GEMM (per-token cosine ~0). - local_workspace is passed with a static cute layout (not mark_layout_dynamic), matching the kernel region-offset contract. - AutoTuner input pre-hook only sanitizes the regenerated dynamic inputs and leaves the static per-expert weight scales / alphas untouched. - deepgemm-graph NVFP4 reference (NVFP4RefMegaMoECuteDsl) for accuracy checks. Verified on GB200: single-GPU test_moe_backend / test_moe_module megamoe_cutedsl cases pass (per-token cosine ~1.0), and multi-GPU DEP (EP) cases pass. Signed-off-by: xxi <xxi@nvidia.com>
1 parent a50b5e2 commit d1e8b8b

46 files changed

Lines changed: 19967 additions & 166 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/trtllm-moe-develop/SKILL.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,26 @@ Checklist:
268268
- Existing legacy `forward` methods can be read for compatibility context, but
269269
they are not the default pattern for new backend work.
270270

271+
### Imported Kernel ABI Checklist
272+
273+
When importing or wrapping an upstream kernel, derive the TRT-LLM adapter
274+
contract from the lowest-level kernel consumer. Comments, docs, design notes,
275+
and parameter names are useful hints, but they are not proof of the runtime ABI.
276+
277+
- Derive weight shape and layout from the kernel entrypoint, `make_layout`, TMA,
278+
MMA/GEMM transforms, and stride usage. Record required tensor shape, stride,
279+
physical storage layout, and boundary view layout.
280+
- Derive alpha and scale semantics from kernel consumption points. Trace where
281+
alpha, norm constants, block scales, activation scales, and weight scales are
282+
loaded and multiplied before deciding how upper layers compute or pack them.
283+
Treat weight bytes, block scales/SF, and global alpha/norm constants as
284+
separate contracts.
285+
- Design the upper-layer adapter from the kernel ABI upward. Map each kernel
286+
input/output to an adapter responsibility: storage tensor, view/transposition,
287+
dtype reinterpretation, padding, scale packing, workspace ownership,
288+
synchronization, and output reduction. Validate parity with upstream
289+
invocation dumps, not just final output.
290+
271291
### Quantization And Weights
272292

273293
Role:

.pre-commit-config.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,22 @@ common-files: &common_files |
302302
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/custom_pipeline.py |
303303
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/dense_blockscaled_gemm_persistent.py |
304304
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/utils.py |
305+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/config.py |
306+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/contract.py |
307+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/custom_ext.py |
308+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/dispatch_kernel.py |
309+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/epilogue.py |
310+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/fc1_fc2_fuse_sched.py |
311+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/grid_sync.py |
312+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/iket_compat.py |
313+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/kernel_fc12.py |
314+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_constants.py |
315+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_kernel.py |
316+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_persistent_scheduler.py |
317+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_utils.py |
318+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/ptx_helpers.py |
319+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sf_swizzle.py |
320+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sym_buffer.py |
305321
tensorrt_llm/_torch/cute_dsl_utils.py |
306322
tensorrt_llm/_torch/debug/__init__.py |
307323
tensorrt_llm/_torch/debug/debug_hook.py |
@@ -1658,6 +1674,22 @@ legacy-files: &legacy_files |
16581674
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/custom_pipeline.py |
16591675
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/dense_blockscaled_gemm_persistent.py |
16601676
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/utils.py |
1677+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/config.py |
1678+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/contract.py |
1679+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/custom_ext.py |
1680+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/dispatch_kernel.py |
1681+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/epilogue.py |
1682+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/fc1_fc2_fuse_sched.py |
1683+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/grid_sync.py |
1684+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/iket_compat.py |
1685+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/kernel_fc12.py |
1686+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_constants.py |
1687+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_kernel.py |
1688+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_persistent_scheduler.py |
1689+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_utils.py |
1690+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/ptx_helpers.py |
1691+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sf_swizzle.py |
1692+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sym_buffer.py |
16611693
tensorrt_llm/_torch/cute_dsl_utils.py |
16621694
tensorrt_llm/_torch/debug/__init__.py |
16631695
tensorrt_llm/_torch/debug/debug_hook.py |

legacy-files.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,22 @@ tensorrt_llm/_torch/cute_dsl_kernels/blackwell/__init__.py
294294
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/custom_pipeline.py
295295
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/dense_blockscaled_gemm_persistent.py
296296
tensorrt_llm/_torch/cute_dsl_kernels/blackwell/utils.py
297+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/config.py
298+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/contract.py
299+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/custom_ext.py
300+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/dispatch_kernel.py
301+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/epilogue.py
302+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/fc1_fc2_fuse_sched.py
303+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/grid_sync.py
304+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/iket_compat.py
305+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/kernel_fc12.py
306+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_constants.py
307+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_kernel.py
308+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_persistent_scheduler.py
309+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_utils.py
310+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/ptx_helpers.py
311+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sf_swizzle.py
312+
tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sym_buffer.py
297313
tensorrt_llm/_torch/cute_dsl_utils.py
298314
tensorrt_llm/_torch/debug/__init__.py
299315
tensorrt_llm/_torch/debug/debug_hook.py

pyproject.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,22 @@ exclude = [
352352
"tensorrt_llm/_torch/cute_dsl_kernels/blackwell/custom_pipeline.py",
353353
"tensorrt_llm/_torch/cute_dsl_kernels/blackwell/dense_blockscaled_gemm_persistent.py",
354354
"tensorrt_llm/_torch/cute_dsl_kernels/blackwell/utils.py",
355+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/config.py",
356+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/contract.py",
357+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/custom_ext.py",
358+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/dispatch_kernel.py",
359+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/epilogue.py",
360+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/fc1_fc2_fuse_sched.py",
361+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/grid_sync.py",
362+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/iket_compat.py",
363+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/kernel_fc12.py",
364+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_constants.py",
365+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_kernel.py",
366+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_persistent_scheduler.py",
367+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_utils.py",
368+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/ptx_helpers.py",
369+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sf_swizzle.py",
370+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sym_buffer.py",
355371
"tensorrt_llm/_torch/cute_dsl_utils.py",
356372
"tensorrt_llm/_torch/debug/__init__.py",
357373
"tensorrt_llm/_torch/debug/debug_hook.py",

ruff-legacy.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,22 @@ include = [
311311
"tensorrt_llm/_torch/cute_dsl_kernels/blackwell/custom_pipeline.py",
312312
"tensorrt_llm/_torch/cute_dsl_kernels/blackwell/dense_blockscaled_gemm_persistent.py",
313313
"tensorrt_llm/_torch/cute_dsl_kernels/blackwell/utils.py",
314+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/config.py",
315+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/contract.py",
316+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/custom_ext.py",
317+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/dispatch_kernel.py",
318+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/epilogue.py",
319+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/fc1_fc2_fuse_sched.py",
320+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/grid_sync.py",
321+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/iket_compat.py",
322+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/kernel_fc12.py",
323+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_constants.py",
324+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/megamoe_kernel.py",
325+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_persistent_scheduler.py",
326+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/moe_utils.py",
327+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/ptx_helpers.py",
328+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sf_swizzle.py",
329+
"tensorrt_llm/_torch/cute_dsl_kernels/mega_moe_nvfp4/sym_buffer.py",
314330
"tensorrt_llm/_torch/cute_dsl_utils.py",
315331
"tensorrt_llm/_torch/debug/__init__.py",
316332
"tensorrt_llm/_torch/debug/debug_hook.py",

tensorrt_llm/_torch/autotuner.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,8 +1468,7 @@ def _create_tensor_like(self, origin_tensor: torch.Tensor,
14681468
if dtype == torch.float4_e2m1fn_x2:
14691469
return (torch.rand(shapes, device=device) * 10 - 5).to(
14701470
torch.uint8).view(dtype)
1471-
else:
1472-
return (torch.rand(shapes, device=device) * 10 - 5).to(dtype)
1471+
return (torch.rand(shapes, device=device) * 10 - 5).to(dtype)
14731472

14741473
def _prepare_input_tensors(
14751474
self, profile: OptimizationProfile,

tensorrt_llm/_torch/custom_ops/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ def inplace_slice_copy(dest: torch.Tensor, src: torch.Tensor, dim1_start: int,
5858
'cute_dsl_nvfp4_dense_gemm_swiglu_fp4out_blackwell',
5959
]
6060

61+
# MegaMoE NVFP4 op probes a strict superset of IS_CUTLASS_DSL_AVAILABLE
62+
# (cutlass.torch + cutlass._mlir + cute_nvgpu MMA atoms + the ported
63+
# CuteDSL kernel package). The cute_dsl_megamoe_custom_op module
64+
# sets ``IS_MEGAMOE_OP_AVAILABLE`` based on its own try/except probe;
65+
# importing the module is safe regardless of the result -- it just
66+
# logs and leaves ``IS_MEGAMOE_OP_AVAILABLE = False`` on partial
67+
# cutlass-dsl installs so callers can fall back via the factory.
68+
from .cute_dsl_megamoe_custom_op import IS_MEGAMOE_OP_AVAILABLE
69+
if IS_MEGAMOE_OP_AVAILABLE:
70+
from .cute_dsl_megamoe_custom_op import cute_dsl_megamoe_nvfp4_blackwell
71+
__all__ += ['cute_dsl_megamoe_nvfp4_blackwell']
72+
6173
if IS_CUDA_TILE_AVAILABLE:
6274
from .cuda_tile_custom_ops import (cuda_tile_rms_norm,
6375
cuda_tile_rms_norm_fuse_residual_)

0 commit comments

Comments
 (0)