Add an opt-in Helion kernel backend for the Mamba-2 SSD path - #1012
Open
shcho1118 wants to merge 13 commits into
Open
Add an opt-in Helion kernel backend for the Mamba-2 SSD path#1012shcho1118 wants to merge 13 commits into
shcho1118 wants to merge 13 commits into
Conversation
ssd_combined resolves its kernels through _ssd_kernel_impls(), which returns the Triton namespace unless MAMBA_USE_HELION=1, so the default path is unchanged and the helion package is imported only after the opt-in is confirmed.
Shadow every dispatched kernel inside one MambaMixerMin fwd+bwd that runs on Triton, so both implementations are compared on production arguments while the pipeline stays on the reference path.
Attribute profiler device time to the dispatch stage that launched it, since the two backends emit differently named kernels.
Tuned on B200 with helion 1.4.0 / triton 3.6.0 at the autotune harness defaults; the directory name and its README record the axes a config set is specific to.
Cover enabling it, autotuning configs, the tests and the benchmark, with a measured per-stage comparison from the checked-in config set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t_kernels Move D/gated-norm-weight randomization into MambaMixerMin's constructor so autotune_baseline_fn's accuracy check also exercises non-degenerate values, not just the test. Also print diff/magnitude stats when a kernel comparison passes, to make tolerance margins visible. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Helion implementation of the nine SSD kernels behind
mamba_split_conv1d_scan_combined, plus the gated-LayerNorm backward, selected at runtime byMAMBA_USE_HELION=1. On a B200 it cuts the device time of those stages by 1.39x (fwd+bwd, seq 8192, bf16). Without the env var nothing changes: the Triton kernels stay the default and the numerical reference, andheliondoes not even have to be installed.Design
The Triton path is untouched. The only changes to existing code are +38/-13 lines in two files, and they are pure indirection — the added lines are mostly a namespace listing the nine Triton kernels:
ssd_combined.py— the nine Triton kernels are collected into_TRITON_SSD_KERNELS, and_ssd_kernel_impls()returns that namespace, or the Helion one under the opt-in. The fwd/bwd functions resolve it once and call through it.layernorm_gated.py—LayerNormFn.backwardpicks the Helion_layer_norm_bwdover the Triton one.Dispatch is opt-in and lazy.
mamba_ssm/ops/helion/dispatch.pyis the only import of the new package from production code, and it imports the kernels — and thereforehelionitself — only afterMAMBA_USE_HELION=1is confirmed. An install withouthelionimports and runs exactly as before.Configs are files, never autotuned at runtime. Each kernel resolves its Helion config from
MAMBA_HELION_CONFIG_DIR/<kernel>.jsonon first call; a missing config is a hard error unlessMAMBA_HELION_AUTOTUNEis set explicitly. Autotuning must not happen under CUDA graph capture or in a distributed job, so it is an offline step run by a harness inbenchmarks/helion/, which also verifies that every dispatched kernel left a config behind.New code lives in
mamba_ssm/ops/helion/(runtime: dispatch, config loading, one file per kernel) andbenchmarks/helion/(offline: autotune harness, benchmark, example configs — excluded from the wheel, so nothing writes into site-packages).Measurements
Device time per fwd+bwd iteration,
MambaMixerMin(a Megatron-free replica of Megatron-LM'sMambaMixer._ssm_traininglayout) at Nemotron3-Nano dimensions:d_model2688, 64 heads x 64,d_state128, 8 groups,chunk_size128, seq_len 8192, batch 1, bf16, unpacked. NVIDIA B200, torch 2.11.0a0 (NGC 26.03, CUDA 13.2), triton 3.6.0, helion 1.4.0.The left group is each dispatch stage's whole device time, including the aten helpers it launches; the right group is the generated Triton/Helion kernel alone.
layer_norm_bwdchunk_scan_fwdchunk_scan_chunk_state_bwd_dxchunk_scan_bwd_ddAcs_stablechunk_state_bwd_dbchunk_state_fwdchunk_scan_bwd_dCstate_passing_bwdstate_passing_fwdchunk_scan_bwd_dstatesAttribution is per dispatch stage rather than per kernel name, because the two backends emit differently named kernels; the two column groups are split because they leave different amounts of work to aten (e.g. Triton reduces
dDwith a separatereduce_kernelwhere Helion uses in-kernel atomics).Reproduce with
python benchmarks/helion/bench_mamba_mixer.py(profiles both backends in separate subprocesses and prints the table).Testing
pip install -e '.[helion,causal-conv1d]' --no-build-isolation pytest tests/ops/helion/test_kernels.pytests/ops/helion/test_kernels.pycompares every kernel with its Triton reference inside a real pass: oneMambaMixerMinfwd+bwd runs with the pipeline on Triton, and each dispatched kernel is wrapped so both implementations are invoked on the same production arguments and their outputs compared. The wrapper returns the Triton result, so every later stage still consumes exact production data and a mismatch is attributable to the kernel that produced it. Arguments are never rebuilt by hand — they are views into shared buffers (x/B/C/dxslice one packedxBC) and outputs of preceding stages, and Helion compiles per stride, so a contiguous stand-in would test a specialization that never runs.Tolerances are one bf16 ulp for
rtolplus an absolute floor of one ulp of the tensor's own max magnitude, since these outputs span five orders of magnitude in element size. WithMAMBA_HELION_CONFIG_DIRunset the tests use the config set checked in underbenchmarks/helion/configs/, so no environment setup is needed; if that set does not fit the GPU or toolchain, the failure carries the command to autotune a new one. The packed (THD) path is covered byMAMBA_HELION_TEST_PACKED=1with its own config set.Existing suites were run on this branch with
MAMBA_USE_HELIONunset, where the dispatch resolves to the same Triton functions as before:test_layernorm_gated.py40 passed / 24 skipped,tests/test_determinism.py35 passed,tests/ops/triton/test_ssd.py23 passed withtest_chunk_state_varlen[128-max-dtype2]failing. That one failure reproduces identically on the merge base without this branch, so it is pre-existing and unrelated.Limitations, and questions for maintainers
use_deterministic_mode():chunk_scan_chunk_state_bwd_dx(ddt, 1-D dD) andchunk_scan_bwd_dC(ddA_cumsum_prev) always reduce with atomic adds. Enabling both warns once, and the Triton path remains the deterministic one. If you would rather the backend refuse to run in deterministic mode, that is a small change.helionextra pinshelion==1.4.0rather than lower-bounding it, because a config is autotuned against one toolchain and Helion's config schema is still moving; bumping the pin means re-autotuning the checked-in set. Say the word if you would rather carry a range.helion; theyimportorskipand skip cleanly otherwise, so they are inert in CPU CI. I can wire them into a workflow if there is a GPU runner.mamba_mixer_min.pysits in the package rather than inbenchmarks/, because the harness, the benchmark and the tests all import it. Can move it wherever you prefer.Commits
12 commits, each self-contained: the default path is Triton at every commit, and
import mamba_ssmworks withouthelioninstalled at every commit (verified by blocking thehelionimport and importing the package at each one). Kernels land one group at a time, each adding its entry to the dispatch namespace; the harness, tests, benchmark, example configs and docs follow.