Nvfp4 A16 Blackwell Moe Dispatch Policy#
-
namespace trt_edgellm
Argument bundles for the CuTe DSL FMHA launchers.
Each public run* entry point fills one of these once from its own arguments and members, and the launcher then spreads it across the generated descriptors. One struct per wrapper shape rather than a single superset: a superset would let a field that matters on one path (kvCacheCapacity on the dense path, tokensPerPage on the paged one) sit silently at zero on another.
These carry no generated types, so this header is safe to include from translation units that use the required FMHA-v2 runner, the optional CUTE_DSL_FMHA_BLACKWELL_ENABLED runner, or both. The descriptor-filling machinery itself lives in cuteDslTensorDescriptors.h, which stays free of any FMHA concept.
Helpers for populating the tensor descriptors emitted by the CuTe DSL C exporter.
Every AOT variant exports its own nominally distinct but layout-identical descriptor structs (
fmha_d64_Tensor_q_tensor_tvsfmha_d128_Tensor_q_tensor_t) plus acute_dsl_<variant>_wrapperentry point. There is no umbrella C type, so descriptor types are recovered here from the signature of the wrapper that consumes them: a call site names only the wrapper and the kernel module, and pairing a descriptor with the wrong variant is not expressible.The exporter (
cutlass/cute/export/c_header_generator.py) always names the membersdata,dynamic_shapesanddynamic_strides, but emits each array only when its dynamic mask is non-empty. A rank-1 descriptor therefore has nodynamic_stridesmember at all and needs makeCuSeqLenTensor() rather than the strided builders below.Small-vocabulary specialisations of the DSpark sampling and verification kernels.
They differ in how the top-k set is found. DSpark selects it in
topKpasses over the row, each a block-wide max-scan, and drops to a single-threaded walk when top-p is used without top-k ortopKexceeds its parallel bound; that cost scales withtopK. A residual-VQ codebook row is small enough to stage in shared memory, so these kernels instead run one MSB-radix select plus a bitonic sort over the surviving candidates — a single pass whose cost is independent oftopK.Semantics, tensor layouts, and accept/residual/bonus behaviour are identical to the DSpark entry points named in each declaration, which remain the fallback above kCpSpecMaxVocab.
-
namespace kernel
Per-position sum across codec groups (Qwen3.5-Omni speaker codec embedding fold).
Mirrors HF
_get_codec_input_embeddings: concatenate per-group embeddings then sum across the group axis. Implemented here as a single-row reduction so the caller only invokes one kernel per row of the speaker codec template.-
namespace nvfp4_a16_blackwell_moe#
Enums
-
enum class Backend : int32_t#
Backend selection for Nvfp4A16BlackwellMoePlugin (plugin attribute
backend).Values:
-
enumerator kAuto = 0#
token-count policy below
-
enumerator kDecode = 1#
force the CUDA-core decode kernels
-
enumerator kPrefill = 2#
force the tcgen05 grouped GEMM
-
enumerator kAuto = 0#
-
enum class TokenTile : int32_t#
Token (MMA-N) tiles baked into the nvfp4_a16_blackwell_moe AOT group. The tile doubles as the per-expert row padding granularity of the permuted activation buffer.
Values:
-
enumerator kTn8 = 8#
-
enumerator kTn16 = 16#
-
enumerator kTn32 = 32#
-
enumerator kTn64 = 64#
-
enumerator kTn128 = 128#
-
enumerator kTn8 = 8#
Functions
- int64_t maxRowsPadded(
- int64_t const numTokens,
- int64_t const topK,
- int64_t const numExperts,
- int64_t const tile
Conservative padded-row capacity of the permuted activation buffer for a given tile: every expert may waste tile-1 rows. Multiple of
tile.
Variables
-
int32_t kLargestTokenTile = {128}#
-
int32_t kMaxTokenTiles = {1024}#
Upper bound on token tiles per grouped-GEMM launch: the kernel stages tile_group_idx into shared memory once per CTA (MAX_TOKEN_TILES in nvfp4_a16_blackwell_moe_gemm.py). validShape rejects profiles whose padded row count at the selected tile would exceed it (T > ~19k at E=128, topK=6).
-
int32_t kDecodeMaxTokens = {1}#
-
int32_t kDecodeFc1SplitK = {2}#
Decode FC1 split-K: FC1 has only 90 row tiles at T=1 (2.25 waves of 40 resident CTAs on 20 SMs); split-K 2 doubles the CTA count and was the best of {1,2,4,8} in the engine (decode step 11.41 ms vs 11.57 / 11.49 / 11.63). The fp32 partials cost one ~3 us reduce; decode stays deterministic.
-
int32_t kDecodeFc1MaxSplitK = {8}#
Largest FC1 split-K the benchmark override may select; the decode workspace is sized for it so the size recorded at engine build never depends on the environment.
-
int32_t kDecodeFc2SplitK = {8}#
-
int32_t kDecodeFc2PrefetchSlots = {0}#
Decode FC2 slots whose weight tiles are staged into shared memory before the kernel’s PDL wait. Sealed to 0: the larger shared-memory carve-out (18 KB per staged slot for Nemotron) keeps FC2 from co-residing with the shared-expert GEMV on TensorRT’s auxiliary stream, which cost more than the staging saved (decode step 11.44 / 11.51 / 11.52 ms for 0 / 1 / 2 slots). The path stays available through EDGELLM_MOE_DECODE_FC2_PREFETCH or the runner parameter and is exercised by the unit tests.
-
int32_t kDecodeFc2MaxPrefetchSlots = {2}#
-
enum class Backend : int32_t#
-
namespace nvfp4_a16_blackwell_moe#
-
namespace kernel