Kernel Selection in VeOmni

July 28, 2026 · View on GitHub

VeOmni selects optimized kernel implementations for attention, mHC, cross-entropy loss, Liger fused ops (RMSNorm, RoPE, SwiGLU), MoE, and load-balancing loss. All selections are driven by config fields in OpsImplementationConfig.

Quick Reference

Every configurable kernel lives under model.ops_implementation.* in YAML and maps to a field on OpsImplementationConfig (veomni/arguments/arguments_types.py). Below is the full list — if a field is not in this table, it is not a kernel selection knob.

KernelConfig fieldAvailable valuesDefaultSelection time
Attentionattn_implementationeager, sdpa, flash_attention_2, flash_attention_3, flash_attention_4, flex_attention, native-sparse"flash_attention_2"Config __post_init__ + build_foundation_model
DSA indexerdsa_indexer_implementationeager, cudnn (GLM-DSA), tilelang (DeepSeek-V4)"eager"Model build via OpsConfigSlot
DSA attentiondsa_attention_implementationeager, flashmla_cudnn (GLM-DSA), tilelang (DeepSeek-V4)"eager"Model build via OpsConfigSlot
mHCmhc_implementationeager, tilelang (DeepSeek-V4, SM90+)"eager"Model build via three OpSlots (pre, post, head)
Cross-entropy losscross_entropy_loss_implementationeager, liger_kernel, chunk_loss, npu"liger_kernel" (GPU)apply_ops_config() (before model build)
RMSNormrms_norm_implementationeager, liger_kernel, npu, triton (per-model; DeepSeek-V3)"liger_kernel" (GPU)Model registration via ops config singleton
SwiGLU MLPswiglu_mlp_implementationeager, liger_kernel"liger_kernel" (GPU)Model registration via ops config singleton
Rotary embeddingrotary_pos_emb_implementationeager, liger_kernel, npu, triton (per-model; DeepSeek-V3)"liger_kernel" (GPU)Model registration via ops config singleton
Vision rotary embeddingrotary_pos_emb_vision_implementationeager, npu"eager"Model registration via ops config singleton
Gated RMSNormrms_norm_gated_implementationeager, fla, npu"fla" (GPU)Qwen3.5 OpSlot binding
Causal Conv1Dcausal_conv1d_implementationeager, fla, npu"fla" (GPU)Qwen3.5 OpSlot binding
Gated delta rulechunk_gated_delta_rule_implementationeager, fla, flash_qla (SM90), npu, npu_ascendc"fla" (GPU)Qwen3.5 OpSlot binding
Load-balancing lossload_balancing_loss_implementationeager, triton (CUDA; NPU config normalizes this default to eager)"triton"apply_ops_config() (before model build)
MoE expertsmoe_implementationeager, fused_triton, fused_quack (SM90+), fused_npu"fused_triton" (GPU)build_foundation_model

Most optimized-op defaults are GPU-oriented. On Ascend NPU, values still equal to the dataclass defaults automatically resolve to npu for RMSNorm, rotary embedding, vision rotary embedding, and cross-entropy; to fused_npu for MoE; and to eager for SwiGLU and load-balancing loss. Explicit non-default overrides are retained and rejected when unsupported. Qwen3.5's three GatedDeltaNet fields are model-specific and are not auto-resolved: set them to npu explicitly because the causal-convolution and gated-delta-rule eager fallbacks do not support dynamic-batch cu_seqlens.

The per-op fields are typed as plain str (not Literal), so third-party backends can be registered via extra_backends in a model's device_patch.py without modifying OpsImplementationConfig.


Lifecycle Overview

import veomni                                 # (1) import time
  └─ apply_ops_patch()
       └─ apply_veomni_attention_patch()      # register Flash/Flex facade names with SP

OpsImplementationConfig.__post_init__()       # (2) config parse time
  ├─ validate requested backends are available
  ├─ rewrite attn_implementation for SP
  └─ set_ops_config(self)                     # populate singleton

BaseTrainer._build_model()                    # (3) model build time
  └─ build_foundation_model(..., ops_implementation=ops)
       ├─ apply_ops_config(ops)               # install LOSS_MAPPING + GLOBAL patches
       │    ├─ install_loss_mapping(ce_impl)  # partial(ForCausalLMLoss, cross_entropy_fn=<impl>)
       │    └─ apply_global_ops(config)       # load_balancing_loss, etc.
       ├─ apply_veomni_fused_moe_patch(...)   # bind MoE kernel
       ├─ device_patch.py reads ops config     # RMSNorm/RoPE/SwiGLU
       ├─ OpSlot.bind(impl_name)              # per-model OpSlot dispatch
       └─ model init + weight loading

model.forward()                               # (4) runtime
  ├─ attention: ALL_ATTENTION_FUNCTIONS[config._attn_implementation]
  ├─ loss: self.loss_function(...) -> LOSS_MAPPING[...] (pre-bound partial)
  │         OR veomni_causal_lm_loss(...) via OpSlot.use_non_eager_impl guard
  ├─ RMSNorm/RoPE/SwiGLU: Liger or HF default (set at registration)
  ├─ mHC: TileKernels pre/post/head or original Transformers implementation
  └─ MoE: fused_moe_forward(...) or eager loop

Single install point. apply_ops_config is the only place that binds LOSS_MAPPING — there is no separate apply_veomni_loss_patch call. The inner CE kernel (eager / liger / npu) is pre-bound onto the wrapper via functools.partial, so runtime dispatch is just a function call and there is no per-forward "which impl?" lookup.

Ownership. build_foundation_model owns the call to apply_ops_config: when callers pass ops_implementation=ops (trainers do this), it runs apply_ops_config(ops) before constructing the model and reads attn_implementation from ops. Callers that pass neither ops_implementation nor a prior apply_ops_config raise ValueError — there is no silent all-eager fallback. Standalone scripts (tasks/infer/*) construct an explicit OpsImplementationConfig (typically all-eager so inference doesn't depend on Liger / Triton). The DiT trainer is the one exception that calls apply_ops_config manually — it has to populate the singleton before building the condition model, which uses model_class._from_config(...) rather than build_foundation_model. The subsequent build_foundation_model call hits the "singleton-already-installed" branch and leaves the prior config alone.


1. Attention

Config

model:
  ops_implementation:
    attn_implementation: flash_attention_2    # default

Field: OpsImplementationConfig.attn_implementation

Available implementations

ValueKernelSequence ParallelRequirements
eagerPyTorchNo
sdpaF.scaled_dot_product_attentionNo
flash_attention_2Flash Attention v2Yesflash-attn
flash_attention_3Flash Attention v3Yesflash-attn-interface
flash_attention_4Flash Attention v4Yesflash-attn.cute
flex_attentionPyTorch FlexAttentionYesNative BlockMask; CUDA for compiled training
native-sparseSparse attentionNo

When MODELING_BACKEND=veomni (the default), __post_init__ automatically rewrites flash_attention_2/3/4 and flex_attention to VeOmni SP-aware variants (veomni_flash_attention_*_with_sp and veomni_flex_attention_with_sp). All VeOmni names enter one fused_attention_forward facade and then dispatch to the selected backend.

FlexAttention requires a model-provided native BlockMask; VeOmni does not construct model-specific visibility. With Ulysses enabled, the mask must be head-broadcast (BlockMask.shape[1] == 1) because rank-local head indices are not rebased for head-specific masks. See docs/transformers_v5/veomni_fused_attention.md for the full contract.

Key files

  • Config: veomni/arguments/arguments_types.pyOpsImplementationConfig
  • Registration: veomni/ops/kernels/attention/__init__.pyapply_veomni_attention_patch()
  • Plumbing: veomni/models/auto.pybuild_foundation_model(ops_implementation=...)

DeepSeek V4 DSA and mHC

DeepSeek V4 exposes three independent model-specific selections. The TileLang indexer and sparse attention backends support packed dynamic batches; the TileKernels mHC backend replaces the pre/Sinkhorn/collapse, residual post-mix, and final head collapse through registry-backed OpSlots:

model:
  ops_implementation:
    dsa_indexer_implementation: tilelang
    dsa_attention_implementation: tilelang
    mhc_implementation: tilelang

All three optimized paths require NVIDIA SM90 or later. mhc_implementation defaults to eager and never silently falls back after tilelang is selected. The mHC implementation is provided by the tile-kernels package. TileKernels' training path supports forward and backward with BF16 activations and DeepSeek V4's hc_mult=4 layout.


2. Cross-Entropy Loss

Config

model:
  ops_implementation:
    cross_entropy_loss_implementation: liger_kernel   # default; set to "chunk_loss" / "npu" / "eager" on NPU

Field: OpsImplementationConfig.cross_entropy_loss_implementation

Available implementations

ValueImplementationRequirements
liger_kernelfused_liger_kernel_cross_entropyliger-kernel package
npuchunk_loss_function (chunked loss for ForCausalLM and ForConditionalGeneration; SP reduction handled internally)torch_npu
eagereager_cross_entropy (PyTorch F.cross_entropy)

The npu chunk-loss binds only to ForCausalLM and ForConditionalGeneration; ForSequenceClassification stays on eager_cross_entropy because chunk_loss hard-codes the causal labels[..., 1:] shift (incompatible with token-level classification labels).

Selecting liger_kernel requires that the model's forward pass pass hidden_states= and weights=self.lm_head.weight through self.loss_function(...) — the Liger fused linear+CE kernel does the projection itself and has no full logits tensor to fall back on. VeOmni's patched modeling files (patched_modeling_*.py) already do this. If a model whose forward was not patched calls self.loss_function without these kwargs while cross_entropy_loss_implementation="liger_kernel", the Liger kernel raises RuntimeError with a pointer to the patch pattern — it does not silently fall back to eager. Switch the field to eager if the model cannot be patched.

Key files

  • Dispatch: veomni/ops/kernels/cross_entropy/__init__.pyinstall_loss_mapping(impl)
  • Eager impl: veomni/ops/kernels/cross_entropy/eager.py
  • Liger impl: veomni/ops/kernels/cross_entropy/liger.py
  • NPU chunk loss: veomni/ops/kernels/cross_entropy/chunk_loss.pychunk_loss_function

3. Per-Model Ops (RMSNorm, RoPE, SwiGLU MLP)

Each operation can be independently controlled. Despite the historical "Liger fused ops" label, these fields are not Liger-only: they also accept npu (for Ascend NPU backends) and triton (for model-specific Triton kernels registered in the model's device_patch.py, e.g. DeepSeek-V3's batch-invariant RMSNorm and deterministic RoPE).

Config

model:
  ops_implementation:
    rms_norm_implementation: liger_kernel       # default; pin to "npu" / "eager" on NPU
    swiglu_mlp_implementation: liger_kernel     # default; pin to "eager" on NPU (no NPU backend)
    rotary_pos_emb_implementation: liger_kernel # default; pin to "npu" / "eager" on NPU

Available implementations

rms_norm_implementation

ValueImplementationRequirements
liger_kernelLigerRMSNormliger-kernel package
nputorch_npu.npu_rms_normtorch_npu
tritonModel-specific Triton kernel registered via extra_backends (e.g. DeepSeek-V3 batch-invariant RMSNorm)triton, per-model registration
eagerHuggingFace default ({Model}RMSNorm)

rotary_pos_emb_implementation

ValueImplementationRequirements
liger_kernelliger_rotary_pos_embliger-kernel package
nputorch_npu.npu_rotary_multorch_npu
tritonModel-specific Triton kernel registered via extra_backends (e.g. DeepSeek-V3 deterministic RoPE)triton, per-model registration
eagerHuggingFace default (apply_rotary_pos_emb)

swiglu_mlp_implementation

ValueImplementationRequirements
liger_kernelLigerSwiGLUMLPliger-kernel package
eagerHuggingFace default ({Model}MLP)

What gets patched

For each selected backend, a model either applies a device_patch.py target replacement or adds an OpSlot guard in its patchgen-generated forward. Functional OpSlots preserve model-specific constructors and can also pass model-specific arguments such as an optional RMSNorm weight:

Config fieldOriginalLiger replacement
rms_norm_implementation{Model}RMSNormFunctional Liger RMSNorm
rotary_pos_emb_implementationapply_rotary_pos_embliger_rotary_pos_emb
swiglu_mlp_implementation{Model}MLP.forwardFunctional Liger SwiGLU

The npu and triton backends follow the same device_patch.py flow — the only difference is the kernel callable on the other side of the registry.

Models with Liger support

Qwen2, Qwen3, Qwen3-MoE, Qwen2-VL, DeepSeek-V3, DeepSeek-V4, Llama, Seed-OSS. DeepSeek-V4 supports weighted and unweighted RMSNorm plus a clamp-preserving Liger silu*mul path for shared experts; its partial interleaved RoPE remains eager-only.

Key files

  • Config singleton: veomni/ops/config/singleton.pyget_ops_config(), set_ops_config()
  • Unified registry: veomni/ops/config/registry.pyregister_op(), apply_per_model_patches(), apply_global_ops()
  • OSS backend registration: veomni/ops/kernels/{rms_norm,rotary,swiglu}/__init__.py
  • Per-model extra_backends (e.g. DeepSeek-V3 Triton): veomni/models/transformers/{model}/device_patch.py

4. Qwen3.5 GatedDeltaNet Ops

Qwen3.5 exposes three additional OpSlot-driven fields. They default to the GPU fla implementations, so NPU users must select npu explicitly:

model:
  ops_implementation:
    rms_norm_gated_implementation: npu
    causal_conv1d_implementation: npu
    chunk_gated_delta_rule_implementation: npu
FieldGPU valuesNPU valueEager limitation
rms_norm_gated_implementationflanpuHuggingFace reference implementation
causal_conv1d_implementationflanpuNo cu_seqlens path
chunk_gated_delta_rule_implementationfla, flash_qla (SM90 only)npu, npu_ascendcNo cu_seqlens path

The NPU gated RMSNorm uses torch_npu. The NPU causal Conv1D and gated delta-rule implementations additionally require triton-ascend. For the gated delta rule there are two NPU backends: npu (the vendored MindSpeed-MM Triton kernel) and npu_ascendc (an AscendC fused torch.ops.npu.* path), the latter requiring a manual fla_npu install. Registrations live in veomni/ops/kernels/gated_delta_rule/__init__.py; field defaults and allowed values are documented by OpsImplementationConfig.


5. Load-Balancing Loss

Config

model:
  ops_implementation:
    load_balancing_loss_implementation: triton   # CUDA
    # load_balancing_loss_implementation: eager  # NPU

Field: OpsImplementationConfig.load_balancing_loss_implementation

Available implementations

ValueImplementationRequirements
tritonFused Triton kernel (_load_balancing_loss is rebound by apply_ops_config via the registry's global_slot)triton on CUDA
eagerPure-PyTorch reference (load_balancing_loss_pytorch)

Normal NPU config construction maps every value equal to the dataclass default triton—including an explicit YAML value—to eager before registry binding. The optimized triton implementation is CUDA-only; select eager in current NPU configs.

This is a GLOBAL-scope op: the function pointer veomni.ops.kernels.load_balancing_loss._load_balancing_loss is rebound once per process from apply_ops_config(), and every call site that imports from veomni.ops import load_balancing_loss_func picks up the selected backend automatically — no per-model patching needed.

Key files

  • Selection: veomni/ops/kernels/load_balancing_loss/__init__.pyregister_op(...) entry
  • Triton impl: veomni/ops/kernels/load_balancing_loss/triton.py
  • Eager impl: veomni/ops/kernels/load_balancing_loss/eager.py

6. MoE Kernel

Config

model:
  ops_implementation:
    moe_implementation: fused_triton   # Triton group-gemm (GPU, SM70+)
    # moe_implementation: fused_quack  # Quack CUTLASS/CuTe (GPU, SM90+)
    # moe_implementation: fused_npu    # NPU group-gemm (Ascend)
    # moe_implementation: eager        # Reference PyTorch loop (very slow, debug only)

Field: OpsImplementationConfig.moe_implementation Default: "fused_triton" (GPU). On NPU, a value still equal to this dataclass default—including an explicit YAML value—is normalized to "fused_npu". Set "fused_npu" explicitly for clarity; incompatible non-default overrides such as "fused_quack" raise at config validation time.

The mode and kernel backend are expressed as a single field. After the default-value compatibility normalization above, remaining hardware mismatches raise during config validation or kernel binding.

ValueKernelHardwareEP support
eagerPyTorch expert loopAnyNo
fused_tritonTriton group-gemmGPU, SM70+ (V100+)Yes
fused_quackQuack CUTLASS/CuTeGPU, SM90+ (H100+)No
fused_npuNPU group-gemmAscend NPUYes

DeepSeek-V4 keeps eager DSA indexer and attention as its defaults, with optional SM90+ tilelang indexer and attention implementations. Its MoE path uses the independent moe_implementation selection and therefore defaults to fused_triton on GPU. The v4-specific patched experts path passes the merged gate_up_proj tensor directly to fused_moe_forward(...) and forwards swiglu_limit so backends that implement the clamp preserve V4's clamped SwiGLU pre-activation semantics. Clamp-aware fused V4 support is GPU-only today (fused_triton / fused_quack); selecting fused_npu for a V4 model raises because the NPU fused MoE kernel does not yet implement swiglu_limit.

Key files

  • Config: veomni/arguments/arguments_types.pyOpsImplementationConfig
  • Dispatch: veomni/ops/kernels/moe/__init__.pyapply_veomni_fused_moe_patch()
  • Plumbing: veomni/models/auto.pybuild_foundation_model(ops_implementation=...)

Environment Variables

Env varDefaultScopeNotes
MODELING_BACKEND"veomni"Global"veomni" or "hf" — controls whether VeOmni ops patches are applied

Kernel selection is otherwise driven by OpsImplementationConfig fields. The VEOMNI_USE_LIGER_KERNEL and USE_GROUP_GEMM environment variables have been removed in favor of the per-op config fields.

All remaining env vars are registered in veomni/utils/env.py with defaults and can be overridden by setting the corresponding shell environment variable.


7. Comparison with Transformers v5 Kernel Selection

VeOmni targets Transformers 5.9.0, whose kernel selection APIs replace the ad-hoc patching used in earlier versions. This section compares VeOmni's approach (Sections 1-6 above) with the four mechanisms available in Transformers v5, using Qwen3MoE and Qwen3.5MoE as reference models.

7.1 Transformers v5 Mechanisms Overview

#MechanismDecorator / APIWhat it replacesScope
1Hub kernel layers@use_kernel_forward_from_hub("RMSNorm")nn.Module.forwardPer-class, via kernels library from HF Hub
2Hub kernel functions@use_kernel_func_from_hub("rotary_pos_emb")Standalone functions (e.g. apply_rotary_pos_emb)Per-function, via kernels library from HF Hub
3Attention interfaceALL_ATTENTION_FUNCTIONS.get_interface(...)Attention forward passPer-model via config._attn_implementation
4Experts interface@use_experts_implementationMoE expert forward passPer-class via config._experts_implementation

All four are defined in transformers.integrations:

  • hub_kernels.py — mechanisms 1 & 2
  • moe.py — mechanism 4
  • modeling_utils.py — mechanism 3 (ALL_ATTENTION_FUNCTIONS)

7.2 Side-by-Side Comparison

RMSNorm

VeOmniTransformers v5
MechanismThe per-model registry or a variant-aware OpSlot selects liger_kernel, npu, or a model-specific triton backend@use_kernel_forward_from_hub("RMSNorm") decorator on Qwen3MoeRMSNorm; at model.kernelize() time the kernels library downloads and swaps in LigerRMSNorm from kernels-community/liger_kernels
ConfigOpsImplementationConfig.rms_norm_implementation field (default "liger_kernel" on GPU)USE_HUB_KERNELS env var + model.kernelize() call
WhenModel registration (import time)Deferred — kernelize() after model init
SP supportN/A (norm is local)N/A
Qwen3.5 MoE gapCovered by the qwen3_5 OpSlot variant, including offset-aware Liger and NPU kernelsNot annotated. Qwen3_5MoeRMSNorm uses weight * (1.0 + self.weight) (offset-by-1 convention, weight init to zeros) instead of the standard self.weight * x (weight init to ones). No @use_kernel_forward_from_hub("RMSNorm") decorator. Standard LigerRMSNorm cannot replace it without accounting for the +1.0 offset.

Rotary Position Embedding (RoPE)

VeOmniTransformers v5
MechanismThe per-model registry or variant-aware OpSlot selects liger_kernel, npu, or a model-specific triton backend@use_kernel_func_from_hub("rotary_pos_emb") on the apply_rotary_pos_emb function; kernels library downloads apply_rotary_transformers from kernels-community/rotary. The function is also attached to the Attention module via @use_kernelized_func(apply_rotary_pos_emb) so kernelize() can find it.
ConfigOpsImplementationConfig.rotary_pos_emb_implementation field (default "liger_kernel" on GPU)USE_HUB_KERNELS env var
WhenModel registration (import time)Import time (decorator) + kernelize()
Qwen3.5 MoE gapCovered on NPU by the rotary_pos_emb/partial OpSlot variantPartially annotated. apply_rotary_pos_emb in Qwen3_5MoeAttention is annotated with @use_kernelized_func but not with @use_kernel_func_from_hub("rotary_pos_emb"). This is because Qwen3.5 MoE uses partial RoPE (partial_rotary_factor < 1.0): it splits Q/K into rotary and pass-through parts, applies RoPE only to the rotary part, then concatenates. The standard hub kernel apply_rotary_transformers does not handle this split-and-concat pattern. A dedicated partial-RoPE kernel could still be used.

Attention

VeOmniTransformers v5
Mechanismapply_veomni_attention_patch() registers SP-wrapped variants (veomni_flash_attention_2_with_sp, etc.) into ALL_ATTENTION_FUNCTIONSSame ALL_ATTENTION_FUNCTIONS registry. Additionally supports hub-based attention kernels via attn_implementation="kernels-community/flash-mla" syntax (loaded by load_and_register_attn_kernel()).
ConfigOpsImplementationConfig.attn_implementationconfig._attn_implementation (set via AutoModel.from_pretrained(attn_implementation=...))
SP rewrite__post_init__ rewrites flash_attention_2veomni_flash_attention_2_with_spNo SP support — upstream Transformers does not handle Ulysses SP
CompatibilityVeOmni registers into the same ALL_ATTENTION_FUNCTIONS registry that Transformers uses, so the two are compatible by design

MoE Experts

VeOmniTransformers v5
MechanismA module-level OpSlot("moe_experts", "standard") is bound at model-build time by _bind_veomni_ops; the patched experts forward checks slot.use_non_eager_impl and either calls veomni.ops.fused_moe_forward(...) (which dispatches to the bound Triton / Quack / NPU kernel) or falls through to the eager expert loop. The actual kernel is selected by OpsImplementationConfig.moe_implementation.@use_experts_implementation decorator on Qwen3MoeExperts class; at forward time dispatches via ALL_EXPERTS_FUNCTIONS.get_interface(config._experts_implementation, original_forward). Built-in implementations: "batched_mm" (BMM-based), "grouped_mm" (PyTorch torch.nn.functional.grouped_mm, requires PT 2.9+).
ConfigOpsImplementationConfig.moe_implementation ("eager" / "fused_triton" / "fused_quack" / "fused_npu")config._experts_implementation ("eager" / "batched_mm" / "grouped_mm")
EP supportfused_triton and fused_npu paths support Expert Parallelism via VeOmni's EP shardingbatched_mm handles invalid expert IDs (sentinel >= num_experts) for EP compatibility
WhenDeferred to build_foundation_model()Decorator at class definition time; dispatch at forward time

Note: Transformers v5 hardcodes two MoE experts implementations (batched_mm and grouped_mm) and does not expose a registration interface for external fused kernels, so backends like VeOmni's Triton / Quack / NPU group-gemm must be plugged in through the OpSlot dispatch layer rather than via ALL_EXPERTS_FUNCTIONS.

7.3 Gaps — What Transformers v5 Does NOT Cover

The following areas have kernel selection in VeOmni but no corresponding mechanism in Transformers v5:

1. Fused Cross-Entropy Loss

Transformers v5 uses a loss_function property on PreTrainedModel that looks up LOSS_MAPPING[self.loss_type] — this returns a standard PyTorch F.cross_entropy-based loss. There is no decorator, no hub kernel, and no env-var-based kernel swap for the loss function.

VeOmni replaces this at model-build time via apply_ops_config(...)install_loss_mapping(impl), which binds LOSS_MAPPING["ForCausalLM"] to partial(ForCausalLMLoss, cross_entropy_fn=<impl>) — where <impl> is fused_liger_kernel_cross_entropy (GPU liger_kernel), chunk_loss_function (NPU), or eager_cross_entropy (portable default). The fused Liger cross-entropy computes the loss without materializing the full logits tensor, which significantly reduces memory for large-vocabulary models.

Implication: When using VeOmni's trainer or build_foundation_model with ops_implementation=..., the fused loss is transparent. A standalone Transformers training loop that doesn't go through build_foundation_model would need to call apply_ops_config(OpsImplementationConfig(...)) itself before model construction (or directly monkey-patch LOSS_MAPPING).

2. MoE Load-Balancing Auxiliary Loss

Both Qwen3MoE and Qwen3.5MoE in Transformers v5 include a standalone load_balancing_loss_func() that computes the Switch Transformer auxiliary loss. This function is called directly in Qwen3MoeForCausalLM.forward() — there is no kernel selection, no registry, and no hub kernel for it.

VeOmni adds a configurable Triton implementation through load_balancing_loss_implementation; Transformers itself still has no corresponding selection surface for this function.

3. Qwen3.5 MoE Variant-Specific Ops

Qwen3.5 MoE introduces architectural differences that prevent direct use of the standard hub kernel annotations:

ComponentQwen3 MoEQwen3.5 MoEWhy standard kernel fails
RMSNormself.weight * x (weight init ones)(1.0 + self.weight) * x (weight init zeros)LigerRMSNorm assumes no offset; applying it would produce incorrect results
RoPEFull rotary on all dimsPartial rotary (partial_rotary_factor) — split, rotate, concatHub apply_rotary_transformers assumes full-dim rotation
RMSNormGatedN/AQwen3_5MoeRMSNormGated — norm then SiLU gate multiplyUses explicit fla library selection (see below)

RMSNormGated: explicit fla library selection (not the hub kernel framework)

Unlike RMSNorm and RoPE above, Qwen3.5 MoE's RMSNormGated does have a fused kernel path — but it bypasses the Transformers v5 @use_kernel_forward_from_hub framework entirely. Instead, Qwen3_5MoeGatedDeltaNet.__init__ performs a hard-coded conditional selection at model init time:

# transformers/models/qwen3_5_moe/modeling_qwen3_5_moe.py

# At module top level:
if is_flash_linear_attention_available():
    from fla.modules import FusedRMSNormGated
    from fla.ops.gated_delta_rule import chunk_gated_delta_rule, fused_recurrent_gated_delta_rule
else:
    chunk_gated_delta_rule, fused_recurrent_gated_delta_rule = None, None
    FusedRMSNormGated = None

# In Qwen3_5MoeGatedDeltaNet.__init__:
self.norm = (
    Qwen3_5MoeRMSNormGated(self.head_v_dim, eps=self.layer_norm_epsilon)
    if FusedRMSNormGated is None
    else FusedRMSNormGated(
        self.head_v_dim,
        eps=self.layer_norm_epsilon,
        activation=self.activation,
        device=torch.cuda.current_device(),
        dtype=config.dtype if config.dtype is not None else torch.get_default_dtype(),
    )
)

This is a 5th kernel selection pattern — not covered by any of the four Transformers v5 mechanisms. It is a simple if library_available else fallback check, similar to how the same file selects between causal_conv1d_fn (from the causal-conv1d library) and a pure-PyTorch torch_causal_conv1d_update fallback, and between chunk_gated_delta_rule (from fla.ops) and torch_chunk_gated_delta_rule.

Key characteristics of this pattern:

  • No decorator, no registry, no env var — purely hard-coded if/else in __init__
  • Library: flash-linear-attention (fla) — a separate library from both Liger and the kernels hub
  • Scope: Only the Gated DeltaNet linear attention layers in Qwen3.5 MoE; the standard full-attention Qwen3_5MoeAttention layers do not use this norm
  • Not configurable at runtime — determined solely by whether fla is installed
  • FusedRMSNormGated fuses the RMSNorm + SiLU gate multiply into a single Triton kernel, which the eager Qwen3_5MoeRMSNormGated does in two steps: hidden = weight * (x / rms) then hidden = hidden * silu(gate)

In Transformers v5, these remaining Qwen3.5 MoE ops (RMSNorm with +1 offset, partial RoPE) are left un-annotated — they always run the eager PyTorch implementation. In theory, fused kernels could still be written for each (e.g., a Triton RMSNorm with +1 offset, a partial-RoPE kernel), but no such kernels currently exist in the kernels-community hub.

7.4 Summary Table

ComponentVeOmni mechanismTransformers v5 mechanismCompatible?Gap
RMSNormPer-model registry + variant-aware OpSlot@use_kernel_forward_from_hubParallel — both can applyVeOmni covers Qwen3.5's +1 variant explicitly
RoPEPer-model registry + variant-aware OpSlot@use_kernel_func_from_hub + @use_kernelized_funcParallelVeOmni adds an NPU partial-RoPE variant
SwiGLU MLPPer-model registryNot annotated in MoE models (MLP is per-expert, not standalone)VeOmni only
AttentionALL_ATTENTION_FUNCTIONS (shared registry)ALL_ATTENTION_FUNCTIONS (same registry)YesVeOmni adds SP wrapping
MoE expertsapply_veomni_fused_moe_patch (Triton/Quack)@use_experts_implementation (batched_mm/grouped_mm)No — different dispatch pathsVeOmni uses custom Triton kernels; HF uses PyTorch native grouped_mm
Cross-entropyapply_ops_config + LOSS_MAPPING/OpSlotLOSS_MAPPING (standard F.cross_entropy)VeOmni onlyHF has no fused loss selection
MoE aux lossConfigurable eager/Triton registryEager load_balancing_loss_funcVeOmni onlyHF has no fused selection surface
RMSNormGatedVariant-aware OpSlot (fla/npu/eager)Hard-coded fla.modules.FusedRMSNormGated if fla is installed, else eagerDifferent dispatchVeOmni adds explicit hardware selection

Full Config Example

model:
  ops_implementation:
    attn_implementation: flash_attention_2
    moe_implementation: fused_triton
    cross_entropy_loss_implementation: liger_kernel
    rms_norm_implementation: liger_kernel
    swiglu_mlp_implementation: eager           # disable Liger for MLP only
    rotary_pos_emb_implementation: liger_kernel
    load_balancing_loss_implementation: triton