Skip to content

Introduce Mega-C++ to reduce CPU overhead#3099

Draft
zhongbozhu wants to merge 2 commits into
NVIDIA:mainfrom
zhongbozhu:main_megacpp_grouped_mlp
Draft

Introduce Mega-C++ to reduce CPU overhead#3099
zhongbozhu wants to merge 2 commits into
NVIDIA:mainfrom
zhongbozhu:main_megacpp_grouped_mlp

Conversation

@zhongbozhu

@zhongbozhu zhongbozhu commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Description

Assistant: GPT5.5 codex

Get rid of CPU overhead whenever CUDA Graph is not applicable. Guarded by NVTE_MEGACPP_GROUPED_LINEAR.

Drop-in replace grouped MLP, ie. FC1 - act - FC2. Target BF16 grouped gemm with cublas grouped gemm backend.

In the future, we can extend to mxfp8 / nvfp4 with cublas backend or even cuteDSL grouped gemm and call cute.jit in C++: NVIDIA/cutlass#3289

Recommend CUDA >= 13.2.1

TODO:

  • E2E training with some multimodal THD packing workloads
  • Attach before & after screenshots

Fixes # (issue)

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

Please list the changes introduced in this PR:

  • Change A
  • Change B

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
@github-actions github-actions Bot added the community-contribution PRs from external contributor outside the core maintainers, representing community-driven work. label Jun 6, 2026
@zhongbozhu

Copy link
Copy Markdown
Collaborator Author

/te-ci pytorch L1

m.def("te_general_grouped_gemm_for_discrete_out",
&transformer_engine::pytorch::te_general_grouped_gemm_for_discrete_out,
"Grouped GEMM for discrete output list");
m.def("megacpp_grouped_mlp_forward", &transformer_engine::pytorch::megacpp_grouped_mlp_forward,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should expose these functions within the tex.grouped_mlp_experimental submodule:

// Experimental fused grouped MLP
auto grouped_mlp_experimental = m.def_submodule(
"grouped_mlp_experimental",
"Experimental helpers for the fused grouped MLP (unstable, may change or disappear).");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make more sense to organize:

csrc/
├── extensions/
│   ├── grouped_mlp_experimental/
│   │   ├── megacpp.cpp
│   │   └── grouped_mlp_experimental.cpp
│   ├── pybind.cpp
│   └── ...

If we implement more mega-C++ impls in the future, I don't see a reason why they would be more similar to each other than to the block they are fusing.

name: str
is_scaled: bool
is_gated: bool
glu_interleave_size: int

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth supporting GLU interleaving in the mega-C++ path? The only benefit is to support the fused GEMM+GLU kernel, and otherwise the unnecessary memory-bound kernel means perf is a lost cause. If we can simplify our optimized code paths, then it's worth it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only benefit is to support the fused GEMM+GLU kernel

I do hope in the future we can launch CuteDSL fused kernels in C++ with some TVM-FFI tricks, otherwise we are forced to choose either better kernel fusions or less CPU overhead. Currently the CuteDSL fusion path is very CPU bounded for small models and we rely on CUDA graph and paged stashing for it to work well

Comment on lines +377 to +380
# Explicit env opt-in gives megacpp first chance. Unsupported recipes intentionally
# return the ops unchanged so lower-priority recipe-specific fusers remain the
# fallback path.
register_forward_fusion(fuse_forward_megacpp_ops, prepend=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GEMM+act fusions provide better GPU perf, so I think they should take higher priority than mega-C++. Basically, I see mega-C++ as "we can't do any better on GPU than the unfused impl, but at least we can make the CPU overhead very small".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current order is follows:

  1. check env var
  2. env var = 1, then check supported recipe for mega-C++, so bf16 is supported, not mxfp8 / nvfp4
  3. then for mxfp8, nvfp4, mega-C++ does fallback and check for the next fusion.

The reasoning is that, I do not want the compromise of either better fusion or less host bound, so for future mxfp8 support, we can do the following two things:

  1. directly do cuteDSL integration directly with tvm-ffi and do cublas as a backup plan
  2. maybe add a new value to NVTE_MEGACPP_GROUPED_LINEAR=forced, so for users who cannot enable cuda graph for some reason, they can enforce C++ when they know that their training is more host bound

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution PRs from external contributor outside the core maintainers, representing community-driven work.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants