Skip to content

Migrate norms and softmax kernels to NVRTC - #3156

Merged
timmoon10 merged 12 commits into
NVIDIA:mainfrom
CarlosGomes98:cgomes/nvrtc-phase0
Jul 14, 2026
Merged

Migrate norms and softmax kernels to NVRTC#3156
timmoon10 merged 12 commits into
NVIDIA:mainfrom
CarlosGomes98:cgomes/nvrtc-phase0

Conversation

@CarlosGomes98

@CarlosGomes98CarlosGomes98 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Description

Enables JIT compilation through NVRTC for Norm and Softmax kernels.
Reduces TE binary size by 36%, sequential build time by 5% (measured in cpu_user total time, hard to measure real impact due to parallelization, machine specs)
This is the first chunk of work related to #3054 .

The softmax kernels were chosen as they seemed like one of the simplest to migrate, for my understanding of the system.
The norm kernels include normalization/layernorm/ln_fwd_cuda_kernel.cu, which is one of the heaviest kernel compilations in the build.

It is still possible to enable nvcc static compilation through NVTE_BUILD_LEGACY_STATIC_FUSED_SOFTMAX and NVTE_BUILD_LEGACY_STATIC_NORM, which then allow for NVTE_DISABLE_NVRTC=1 to be used during runtime.

Build time results:

Measured on RTX 6000 Ada, CUDA 12.8, single arch sm_89, 32-core host. AOT = -DNVTE_BUILD_LEGACY_STATIC_{FUSED_SOFTMAX,NORM}=ON (old behavior); NVRTC = default.

Per TU build time

translation unitcompile AOT (s)compile NVRTC (s)Δ time (s)obj AOT (KB)obj NVRTC (KB)Δ size (KB)
scaled_masked_softmax.cu10.802.64−8.22348274−2074
scaled_upper_triang_masked_softmax.cu11.752.51−9.21891238−1653
scaled_aligned_causal_masked_softmax.cu10.242.52−7.72097233−1864
ln_fwd_cuda_kernel.cu63.9028.47−35.49092131−8961
ln_bwd_semi_cuda_kernel.cu43.8028.45−15.45295121−5174
rmsnorm_fwd_cuda_kernel.cu38.2828.39−9.92499114−2385
rmsnorm_bwd_semi_cuda_kernel.cu37.3428.55−8.82566115−2451
total225.0130.5−94.5 (−42%)260601498−24562 (−94%)

Binary size

targetAOT (MB)NVRTC (MB)Δ (MB)
libtransformer_engine.so64.441.2−23.2 (−36%)

Total build time

metricAOTNVRTCΔ
wall (s)283.6210.6−72.9 (−26%)
cpu_user (s)2584.62455.0−129.6 (−5%)
max_rss (MB)403740370

JIT compilation cost

kernelNVRTC cold (ms)static (ms)
layernorm_fwd97.13.5
layernorm_bwd133.12.7
rmsnorm_fwd83.61.0
rmsnorm_bwd106.41.1
scaled_masked_softmax_fwd52.50.7
scaled_masked_softmax_bwd38.8
scaled_upper_triang_softmax_fwd48.30.4
scaled_upper_triang_softmax_bwd42.3
scaled_aligned_causal_softmax_fwd48.50.3

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:

  • Functionality to pass build options to the NVRTC compile manager
  • Softmax kernels through NVRTC
  • rtc_dispatch.cpp to allow NVRTC to work with the registry used by norms. This is the largest chunk of new code.
  • Norm kernels through NVRTC

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

@github-actionsgithub-actionsBot added the community-contribution PRs from external contributor outside the core maintainers, representing community-driven work. label Jun 30, 2026
@CarlosGomes98
CarlosGomes98force-pushed the cgomes/nvrtc-phase0 branch 2 times, most recently from 4e8d10a to 5235723CompareJune 30, 2026 13:00
@CarlosGomes98

Copy link
Copy Markdown
ContributorAuthor

/te-ci pytorch

@greptile-apps

greptile-appsBot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR migrates norm (LayerNorm / RMSNorm) and softmax kernels from ahead-of-time NVCC compilation to JIT compilation via NVRTC, reducing the libtransformer_engine.so binary size by ~36% and build wall time by ~26%. A new rtc_dispatch.cpp replaces the static registry macro with NVRTC-backed closures that compile kernels on first use, with an optional static fallback controlled by NVTE_BUILD_LEGACY_STATIC_NORM / NVTE_BUILD_LEGACY_STATIC_FUSED_SOFTMAX.

  • Adds extra_options and extra_headers parameters to KernelManager::compile, enabling domain-specific headers (norm kernel params, traits) to be injected only where needed; upgrades KernelManager::lock_ from std::mutex to std::shared_mutex with a double-checked compile under unique_lock to fix the prior TOCTOU concern.
  • Replaces std::exp / std::numeric_limits in softmax device code with expf / neg_infinity<T>() for NVRTC compatibility, and guards host-only includes behind #ifndef __CUDACC_RTC__ in all three softmax translation units.
  • Introduces register_launcher and per-variant register_*_tuned/general functions in rtc_dispatch.cpp that replicate the smem, barrier, workspace, and grid-dimension formulae previously embedded in the static launch helpers, with static_assert(ADD_FLAG, \u2026) guards on the RMSNorm BackwardAdd macros to address a previously flagged silent parameter drop.

Confidence Score: 5/5

Safe to merge — the migration is well-contained, the thread-safety model is sound, and the static fallback escape hatches provide a reliable rollback path.

The KernelManager locking upgrade is correctly implemented and resolves the prior TOCTOU concern. All dispatch paths correctly handle the NVRTC-disabled case. The only finding is a dead needs_cooperative capture in register_launcher, which has no behavioral impact.

transformer_engine/common/normalization/rtc_dispatch.cpp — the register_launcher helper carries a dead needs_cooperative parameter/capture that can be cleaned up, but does not affect correctness.

Important Files Changed

FilenameOverview
transformer_engine/common/normalization/rtc_dispatch.cppNew 742-line file implementing NVRTC-backed closures for all norm kernel variants; correctly double-checks compilation under unique_lock, but captures needs_cooperative in register_launcher without ever using it.
transformer_engine/common/util/rtc.cppUpgrades lock from std::mutex to std::shared_mutex with double-checked compile under unique_lock; adds extra_options/extra_headers support; moves is_compiled and launch to shared_lock.
transformer_engine/common/util/rtc.hClean additions: Header struct, launch_cooperative template, set_function_attribute, occupancy_max_active_blocks_per_sm, and mutable shared_mutex.
transformer_engine/common/fused_softmax/scaled_masked_softmax.cuProperly guards host vs. RTC code paths with CUDACC_RTC, replaces std::exp/std::numeric_limits with expf/neg_infinity(), correct rtc_scale cast in forward path.
transformer_engine/common/normalization/rmsnorm/rmsnorm_bwd_semi_cuda_kernel.cuAdds static_assert(ADD_FLAG) guards on BackwardAdd macros and passes ADD_FLAG through to register_rmsnorm_bwd_tuned/general, addressing the previously flagged silent drop.
transformer_engine/common/normalization/kernel_params.hNew file factoring out norm kernel parameter structs from common.h; enables NVRTC to access them as an injected header.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Kernel dispatch call] --> B{NVRTC enabled?}
B -- No --> C{Static fallback registered?}
C -- Yes --> D[Call static fallback fn ptr]
C -- No --> E[NVTE_ERROR: rebuild with NVTE_BUILD_LEGACY_STATIC_NORM]
B -- Yes --> F[KernelManager::is_compiled? shared_lock]
F -- No --> G[KernelManager::compile unique_lock + double-check]
G --> H[nvrtcCreateProgram with extra_headers]
H --> I[nvrtcCompileProgram with extra_options]
I --> J[Cache Kernel in kernel_cache_]
F -- Yes --> K[configure_params?]
J --> K
K -- Yes --> L[occupancy_max_active_blocks_per_sm shared_lock]
L --> M[Set ctas_per_col, barrier_bytes, workspace_bytes]
K -- No --> N{ctas_per_row == 1?}
N -- Yes --> O[launch shared_lock cuLaunchKernel]
N -- No --> P[launch_cooperative shared_lock cuLaunchCooperativeKernel]
P --> Q[For bwd: also launch finalize kernel]
O --> Q
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Kernel dispatch call] --> B{NVRTC enabled?}
B -- No --> C{Static fallback registered?}
C -- Yes --> D[Call static fallback fn ptr]
C -- No --> E[NVTE_ERROR: rebuild with NVTE_BUILD_LEGACY_STATIC_NORM]
B -- Yes --> F[KernelManager::is_compiled? shared_lock]
F -- No --> G[KernelManager::compile unique_lock + double-check]
G --> H[nvrtcCreateProgram with extra_headers]
H --> I[nvrtcCompileProgram with extra_options]
I --> J[Cache Kernel in kernel_cache_]
F -- Yes --> K[configure_params?]
J --> K
K -- Yes --> L[occupancy_max_active_blocks_per_sm shared_lock]
L --> M[Set ctas_per_col, barrier_bytes, workspace_bytes]
K -- No --> N{ctas_per_row == 1?}
N -- Yes --> O[launch shared_lock cuLaunchKernel]
N -- No --> P[launch_cooperative shared_lock cuLaunchCooperativeKernel]
P --> Q[For bwd: also launch finalize kernel]
O --> Q
Loading

Reviews (9): Last reviewed commit: "Merge branch 'main' into cgomes/nvrtc-ph..." | Re-trigger Greptile

Comment threadtransformer_engine/common/util/rtc.cpp Outdated
Comment threadtransformer_engine/common/normalization/rtc_dispatch.cpp
Comment threadtransformer_engine/common/normalization/layernorm/ln_fwd_cuda_kernel.cu Outdated
Comment threadtransformer_engine/common/utils.cuh Outdated
@ptrendx

Copy link
Copy Markdown
Member

/te-ci pytorch

@ptrendxptrendx left a comment

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.

Generally OK. One general comment is that with this move to NVRTC we could actually expand the tuned kernel coverage not just to those predetermined cases, but also to other row lengths (previously we did not want to do that just because of the binary size and the compilation time). This should give a good benefit, since the general kernel is not very efficient compared with the tuned one. I'm not sure even if there is even a need for the general kernel (apart from the very long row lengths that would not fit) in that case.

Comment threaddocs/envvars.rst Outdated
Comment threadtransformer_engine/common/utils.cuh Outdated
Comment threadtests/cpp/operator/test_softmax.cu Outdated
@CarlosGomes98

CarlosGomes98 commented Jul 7, 2026

Copy link
Copy Markdown
ContributorAuthor

One general comment is that with this move to NVRTC we could actually expand the tuned kernel coverage not just to those predetermined cases, but also to other row lengths

I did consider this, but we also rely on the registration for the optimal launch parameters, for different shapes / archs right? I think its a cool idea but would probably defer it to a separate PR

ptrendx
ptrendx previously approved these changes Jul 7, 2026
@ptrendx

Copy link
Copy Markdown
Member

/te-ci

@ptrendx

Copy link
Copy Markdown
Member

Generally speaking the tuning should not be difficult, but I agree that this can be done in a subsequent PR.

@CarlosGomes98
CarlosGomes98force-pushed the cgomes/nvrtc-phase0 branch 2 times, most recently from 5da6586 to 9772be5CompareJuly 8, 2026 11:18
@pggPL

pggPL commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

/te-ci

@timmoon10timmoon10 left a comment

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.

LGTM

@timmoon10

Copy link
Copy Markdown
Member

/te-ci

CarlosGomes98and others added 11 commits July 10, 2026 10:10
Move the fused-softmax and LayerNorm/RMSNorm kernels from build-time template
instantiation to runtime NVRTC compilation, with full coverage of the existing
kernel set so the NVRTC path is the default.
Fused softmax:
- RTC compile/launch path for scaled / scaled-masked / scaled-upper-triangular /
scaled-aligned-causal softmax, keyed by dtype, shape and mask/causal mode.
- NVTE_BUILD_LEGACY_STATIC_FUSED_SOFTMAX (default OFF) restores the static
template dispatch.
Normalization (LayerNorm + RMSNorm, forward + backward):
- Replace the static REGISTER_NORM_LAUNCHER template fanout with an NVRTC
registry that compiles the selected (norm type, direction, dtypes, hidden size,
CTA config) kernel on first use and caches it.
- NVTE_BUILD_LEGACY_STATIC_NORM (default OFF) restores the static launchers.
- NVRTC-safe kernel sources: kernel sources/headers avoid common.h under
__CUDACC_RTC__; add the dtype aliases and a minimal std::is_same/conditional_t
in the RTC build, and replace a zero-length padding array (a GNU extension nvcc
accepts but NVRTC rejects) with a no-padding union specialization.
KernelManager (util/rtc.{h,cpp}) gains occupancy / function-attribute /
cooperative-launch helpers needed by the norm launchers.
Validated on sm_89 (RTX 6000 Ada): full normalization operator suite 192/192,
softmax + NVRTC unit tests pass; libtransformer_engine.so shrinks ~72 MB -> ~65 MB.
On sm_100a the NVRTC norm forward kernel builds where the static instantiation
crashed the compiler.
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: CarlosGomes98 <carlosmiguel.gomes@live.com.pt>
Signed-off-by: Carlos Gomes <cgomes@nvidia.com>
@phu0ngng

Copy link
Copy Markdown
Collaborator

/te-ci

@timmoon10

Copy link
Copy Markdown
Member

/te-ci

@greptile-apps

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@timmoon10
timmoon10 merged commit aef96db into NVIDIA:mainJul 14, 2026
37 of 44 checks passed
@CarlosGomes98
CarlosGomes98 deleted the cgomes/nvrtc-phase0 branch July 20, 2026 07:46
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@CarlosGomes98@ptrendx@pggPL@timmoon10@phu0ngng