pub struct Qwen3SsmLayer {
pub out_proj_dense: Option<DenseWeight>,
/* private fields */
}Expand description
Qwen3-Next SSM/GDN layer (36 of 48 layers).
Supports two QKVZ projection modes:
- Interleaved (80B):
w4a16_gemv_qkvzor GEMV +deinterleave_qkvz - Sequential (3.5-35B): plain GEMV →
[Q|K|V|Z]already in order
Fields§
§out_proj_dense: Option<DenseWeight>Implementations§
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn new_sequential(
input_norm: DenseWeight,
ssm: SsmWeights,
post_attn_norm: DenseWeight,
ffn: FfnComponent,
qkvz_nvfp4: Option<QuantizedWeight>,
qkvz_nvfp4_t: Option<QuantizedWeight>,
out_proj_nvfp4_t: Option<QuantizedWeight>,
config: &ModelConfig,
gpu: &dyn GpuBackend,
) -> Result<Self>
pub fn new_sequential( input_norm: DenseWeight, ssm: SsmWeights, post_attn_norm: DenseWeight, ffn: FfnComponent, qkvz_nvfp4: Option<QuantizedWeight>, qkvz_nvfp4_t: Option<QuantizedWeight>, out_proj_nvfp4_t: Option<QuantizedWeight>, config: &ModelConfig, gpu: &dyn GpuBackend, ) -> Result<Self>
Construct an SSM layer where QKVZ projection output is already sequential.
Used by Qwen3.5 where separate QKV and Z weights are concatenated at load
time into [Q|K|V|Z] row order. The deinterleave_qkvz kernel is skipped
and plain w4a16_gemv writes directly to the deinterleaved buffer.
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
pub fn new( input_norm: DenseWeight, ssm: SsmWeights, post_attn_norm: DenseWeight, ffn: FfnComponent, qkvz_nvfp4: Option<QuantizedWeight>, config: &ModelConfig, gpu: &dyn GpuBackend, ) -> Result<Self>
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn set_fp8_decode_weights(
&mut self,
qkvz: Option<Fp8Weight>,
out_proj: Option<Fp8Weight>,
)
pub fn set_fp8_decode_weights( &mut self, qkvz: Option<Fp8Weight>, out_proj: Option<Fp8Weight>, )
Install native FP8 block-scaled weights for the decode GEMV path.
Inputs MUST be tagged WeightQuantFormat::Fp8BlockScaled — that is
the canonical input format for the w8a16_gemv kernel
(out[n] = sum_k A[k] * E4M3_LUT[B[n,k]] * block_scale[n/BS, k/BS],
see kernels/gb10/common/w8a16_gemv.cu). The kernel reads the
scale buffer at [N/BS, K/BS] BF16 — exactly the shape produced
by load_fp8_block_scaled_as_fp8weight.
This setter does NOT install the raw FP8 DevicePtr fields used by
the prefill fp8_gemm_n128 kernel — that kernel takes no scale
argument and assumes single-scale FP8 (baked-in scale) produced
by bf16_to_fp8. Block-scaled bytes would silently produce wrong
outputs there. For prefill, call set_fp8_prefill_only_weights
separately with single-scale FP8 derived from a BF16 dequant.
Sourcepub fn set_fp8_rowwise_prefill_weights(
&mut self,
qkvz: Option<Fp8Weight>,
out_proj: Option<Fp8Weight>,
)
pub fn set_fp8_rowwise_prefill_weights( &mut self, qkvz: Option<Fp8Weight>, out_proj: Option<Fp8Weight>, )
Install PER-ROW FP8 weights for the row-wise cuBLASLt PREFILL arm
(ATLAS_FP8_ROWWISE=1, mixed-precision compressed-tensors
checkpoints). Decode is untouched and keeps the NVFP4 copy.
The Fp8PerRow assertion is the mirror of set_fp8_decode_weights’s
Fp8BlockScaled one: each setter refuses the other’s layout, so the
two FP8 shapes cannot cross into each other’s kernels. That crossing
does not fault — the smaller buffer is read in-bounds — so an assert
is the only thing that catches it.
Sourcepub fn set_fp8_prefill_only_weights(
&mut self,
qkvz_fp8: Option<DevicePtr>,
out_proj_fp8: Option<DevicePtr>,
)
pub fn set_fp8_prefill_only_weights( &mut self, qkvz_fp8: Option<DevicePtr>, out_proj_fp8: Option<DevicePtr>, )
Set raw FP8 DevicePtrs for the prefill GEMM path ONLY (no decode GEMV
scale fields). Used by the Qwen3.6-27B-FP8 native-FP8 SSM prefill path:
the FP8 buffer here is a single-scale FP8 (BF16 → FP8 truncation; values
already in FP8 range) suitable for fp8_gemm_n128. Decode falls back to
the NVFP4/BF16 paths via the existing qkvz_nvfp4* fields. PCND:
caller decides whether to install — never set implicitly.
Sourcepub fn predequant_for_prefill(
&mut self,
gpu: &dyn GpuBackend,
config: &ModelConfig,
stream: u64,
) -> Result<()>
pub fn predequant_for_prefill( &mut self, gpu: &dyn GpuBackend, config: &ModelConfig, stream: u64, ) -> Result<()>
Pre-dequant NVFP4 → FP8 for QKVZ and out_proj transposed weights. Eliminates per-inference dequant overhead in prefill GEMMs.
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn set_packed_q2_qkvz(&mut self, qkvz: PackedQ2Weight, gpu: &dyn GpuBackend)
pub fn set_packed_q2_qkvz(&mut self, qkvz: PackedQ2Weight, gpu: &dyn GpuBackend)
Install the Tier-1c keep-packed ternary Q2_0 fused in_proj_qkvz
(ATLAS_GGUF_NATIVE_Q2). Decode dispatches q2_0_gemv_vec; prefill
transient-dequants via Self::qkvz_q2_prefill_gemm. out_proj is
unaffected (stays NVFP4). Requires sequential_qkvz (Bonsai concats
[Q|K|V|Z] at load).
The keep-packed MMQ kernels are resolved HERE, not in the constructor: they ship only in GGUF-serving targets, and probing them on models that never install packed-Q2 weights fails the fail-closed boot audit on every other GDN target.
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn set_moe_lora_weights(
&mut self,
router: Option<LoraPair>,
experts: ExpertLoraLayer,
kernels: LoraKernels,
gpu: &dyn GpuBackend,
) -> Result<()>
pub fn set_moe_lora_weights( &mut self, router: Option<LoraPair>, experts: ExpertLoraLayer, kernels: LoraKernels, gpu: &dyn GpuBackend, ) -> Result<()>
Install this GDN layer’s MoE router + routed-expert LoRA onto its
FfnComponent::Moe. Hard-rejects (never silently drops) when the layer’s
FFN is not MoE — an expert/router delta on a dense-FFN GDN layer is a
loader/adapter mismatch.
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn set_ffn_lora_weights(&mut self, ffn: LoraFfnWeights) -> Result<()>
pub fn set_ffn_lora_weights(&mut self, ffn: LoraFfnWeights) -> Result<()>
Install this linear-attention layer’s DENSE-FFN LoRA onto its
FfnComponent::Dense.
The mirror of set_moe_lora_weights for dense-FFN hybrids. A
linear-attention layer carries no attention projections, but on
Qwen3.8-27B it does carry the SwiGLU FFN — all 64 layers do, only 16 of
which are full attention — and real adapters for that architecture ship
gate/up/down for every one of them. Rejecting those rejected three
quarters of the adapter, and the old message could only suggest
retraining with layers_to_transform.
The component is the same DenseFfnLayer the full-attention layers
hold, so the delta path, its pinned dispatch arms and its refusals are
identical here — this only hands it the weights.
Hard-rejects a non-dense FFN rather than dropping the pairs: a dense delta arriving at a MoE or absent FFN is a loader/adapter mismatch, and silently ignoring it would be an adapter that reports success and does nothing — the exact failure this whole change removes.
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn set_out_proj_lora(&mut self, pair: LoraPair, kernels: LoraKernels)
pub fn set_out_proj_lora(&mut self, pair: LoraPair, kernels: LoraKernels)
Install this layer’s GDN out_proj delta.
Separate from set_ffn_lora_weights: that one targets the block’s FFN,
this one the linear-attention block’s own output projection.
Source§impl Qwen3SsmLayer
impl Qwen3SsmLayer
Sourcepub fn set_hc_weights(&mut self, hc: HcWeights)
pub fn set_hc_weights(&mut self, hc: HcWeights)
Attach mHC weights. Both concrete layer types carry them on this
model: the 12 full-attention layers are Qwen3AttentionLayer, the 36
GDN layers are this one.
Trait Implementations§
Source§impl TransformerLayer for Qwen3SsmLayer
impl TransformerLayer for Qwen3SsmLayer
Source§fn as_any_mut(&mut self) -> Option<&mut dyn Any>
fn as_any_mut(&mut self) -> Option<&mut dyn Any>
Downcast hook so the LoRA install walk can reach this layer’s MoE FFN (Feature-1: routed-expert/router deltas exist on GDN layers too).
Source§fn decode_prestage(
&self,
token: u32,
state: &mut dyn LayerState,
gpu: &dyn GpuBackend,
stream: u64,
) -> Result<()>
fn decode_prestage( &self, token: u32, state: &mut dyn LayerState, gpu: &dyn GpuBackend, stream: u64, ) -> Result<()>
PLE’s host half (hash + NVMe fault-in + slot upload), hoisted before graph replay/capture. No-op on the 47 layers without a PLE site.
Source§fn decode_graph_unsupported(&self) -> bool
fn decode_graph_unsupported(&self) -> bool
PLE’s per-seq host hash on the hc multi-seq decode path is capture-illegal (pageable reads); the single-decode path prestages around it, the batched path does not — veto batched graphs.
Source§fn release_state(
&self,
state: &mut dyn LayerState,
gpu: &dyn GpuBackend,
) -> Result<()>
fn release_state( &self, state: &mut dyn LayerState, gpu: &dyn GpuBackend, ) -> Result<()>
Free the PLE carry this sequence lazily attached.
Only the ple field — the h/conv state in SsmLayerState is pooled
and released by slot in free_sequence_dispatch, so freeing it here
would be a double free. The PLE conv buffer is the one piece that is
allocated per sequence and owned by nothing.
Source§fn has_aux_state(&self) -> bool
fn has_aux_state(&self) -> bool
Source§fn snapshot_aux(
&self,
state: &dyn LayerState,
gpu: &dyn GpuBackend,
stream: u64,
) -> Result<Option<Vec<u8>>>
fn snapshot_aux( &self, state: &dyn LayerState, gpu: &dyn GpuBackend, stream: u64, ) -> Result<Option<Vec<u8>>>
copy_d2h_on_stream).
Default: the layer carries no aux sequence state.Source§fn restore_aux(
&self,
state: &mut dyn LayerState,
blob: &[u8],
gpu: &dyn GpuBackend,
stream: u64,
) -> Result<()>
fn restore_aux( &self, state: &mut dyn LayerState, blob: &[u8], gpu: &dyn GpuBackend, stream: u64, ) -> Result<()>
Self::snapshot_aux on a
prefix-cache hit, BEFORE the resumed prefill runs.Source§fn decode_prestage_rearm(&self, state: &mut dyn LayerState)
fn decode_prestage_rearm(&self, state: &mut dyn LayerState)
decode_prestage).Source§fn decode(
&self,
hidden: DevicePtr,
residual: DevicePtr,
state: &mut dyn LayerState,
kv_cache: &mut PagedKvCache,
seq_len: usize,
block_table: &mut Vec<u32>,
disk_block_ids: &mut Vec<u32>,
disk_last_offloaded_per_layer: &mut Vec<u32>,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn decode( &self, hidden: DevicePtr, residual: DevicePtr, state: &mut dyn LayerState, kv_cache: &mut PagedKvCache, seq_len: usize, block_table: &mut Vec<u32>, disk_block_ids: &mut Vec<u32>, disk_last_offloaded_per_layer: &mut Vec<u32>, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
hidden in-place. Read moreSource§fn decode_batched(
&self,
hidden: DevicePtr,
residual: DevicePtr,
num_tokens: usize,
state: &mut dyn LayerState,
_kv_cache: &mut PagedKvCache,
_seq_len: usize,
_block_table: &mut Vec<u32>,
_disk_block_ids: &mut Vec<u32>,
_disk_last_offloaded_per_layer: &mut Vec<u32>,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn decode_batched( &self, hidden: DevicePtr, residual: DevicePtr, num_tokens: usize, state: &mut dyn LayerState, _kv_cache: &mut PagedKvCache, _seq_len: usize, _block_table: &mut Vec<u32>, _disk_block_ids: &mut Vec<u32>, _disk_last_offloaded_per_layer: &mut Vec<u32>, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn decode_verify_multi<'a, 'b: 'a>(
&self,
hidden: DevicePtr,
residual: DevicePtr,
n_seqs: usize,
ks: &[usize],
states: &'a mut [&'b mut (dyn LayerState + 'static)],
_kv_cache: &mut PagedKvCache,
wy_tables: DevicePtr,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn decode_verify_multi<'a, 'b: 'a>( &self, hidden: DevicePtr, residual: DevicePtr, n_seqs: usize, ks: &[usize], states: &'a mut [&'b mut (dyn LayerState + 'static)], _kv_cache: &mut PagedKvCache, wy_tables: DevicePtr, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
n_seqs sequences × k tokens through this layer
in ONE weight sweep (rows seq-major, r = i*k + j, contiguous in
hidden/residual). Projections/FFN batch across all n_seqs*k rows;
the stateful recurrence (conv/GDN) runs per-sequence against
states[i] with row-offset buffer bases — per-sequence math is
byte-identical to the single-sequence decode_batched K-token body. Read moreSource§fn decode_multi_seq<'a, 'b: 'a>(
&self,
hidden: DevicePtr,
residual: DevicePtr,
num_seqs: usize,
states: &'a mut [&'b mut (dyn LayerState + 'static)],
kv_cache: &mut PagedKvCache,
seq_lens: &[usize],
block_tables: &[Vec<u32>],
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn decode_multi_seq<'a, 'b: 'a>( &self, hidden: DevicePtr, residual: DevicePtr, num_seqs: usize, states: &'a mut [&'b mut (dyn LayerState + 'static)], kv_cache: &mut PagedKvCache, seq_lens: &[usize], block_tables: &[Vec<u32>], ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
fn prefill( &self, hidden: DevicePtr, residual: DevicePtr, num_tokens: usize, state: &mut dyn LayerState, kv_cache: &mut PagedKvCache, seq_len_start: usize, block_table: &mut Vec<u32>, disk_block_ids: &mut Vec<u32>, disk_last_offloaded_per_layer: &mut Vec<u32>, kv_write_start: usize, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn is_ssm_layer(&self) -> bool
fn is_ssm_layer(&self) -> bool
Source§fn prefill_phase1(
&self,
hidden: DevicePtr,
residual: DevicePtr,
num_tokens: usize,
state: &mut dyn LayerState,
kv_cache: &mut PagedKvCache,
seq_len_start: usize,
block_table: &mut Vec<u32>,
disk_block_ids: &mut Vec<u32>,
disk_last_offloaded_per_layer: &mut Vec<u32>,
kv_write_start: usize,
gdn_bufs: &GdnPrefillBuffers,
token_offset: usize,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_phase1( &self, hidden: DevicePtr, residual: DevicePtr, num_tokens: usize, state: &mut dyn LayerState, kv_cache: &mut PagedKvCache, seq_len_start: usize, block_table: &mut Vec<u32>, disk_block_ids: &mut Vec<u32>, disk_last_offloaded_per_layer: &mut Vec<u32>, kv_write_start: usize, gdn_bufs: &GdnPrefillBuffers, token_offset: usize, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn prefill_phase1_proj_batched(
&self,
hidden_stacked: DevicePtr,
residual_stacked: DevicePtr,
total_tokens: usize,
gdn_bufs: &GdnPrefillBuffers,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_phase1_proj_batched( &self, hidden_stacked: DevicePtr, residual_stacked: DevicePtr, total_tokens: usize, gdn_bufs: &GdnPrefillBuffers, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
prefill_phase1_conv1d_one per request then prefill_phase1_l2_batched.Source§fn prefill_phase1_conv1d_one(
&self,
state: &mut dyn LayerState,
token_offset: usize,
len: usize,
gdn_bufs: &GdnPrefillBuffers,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_phase1_conv1d_one( &self, state: &mut dyn LayerState, token_offset: usize, len: usize, gdn_bufs: &GdnPrefillBuffers, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn prefill_phase1_l2_batched(
&self,
total_tokens: usize,
gdn_bufs: &GdnPrefillBuffers,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_phase1_l2_batched( &self, total_tokens: usize, gdn_bufs: &GdnPrefillBuffers, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn prefill_gdn_full(
&self,
state: &mut dyn LayerState,
gdn_bufs: &GdnPrefillBuffers,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_gdn_full( &self, state: &mut dyn LayerState, gdn_bufs: &GdnPrefillBuffers, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn prefill_gdn_full_batched(
&self,
h_state_ptrs: DevicePtr,
gdn_bufs: &GdnPrefillBuffers,
batch_size: u32,
chunk_len: u32,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_gdn_full_batched( &self, h_state_ptrs: DevicePtr, gdn_bufs: &GdnPrefillBuffers, batch_size: u32, chunk_len: u32, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn prefill_gdn_full_batched_fla_varlen(
&self,
h_state_ptrs: DevicePtr,
gdn_bufs: &GdnPrefillBuffers,
batch_size: u32,
cu_seqlens: DevicePtr,
max_num_chunks: u32,
total_nt: usize,
max_seqlen: u32,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<bool>
fn prefill_gdn_full_batched_fla_varlen( &self, h_state_ptrs: DevicePtr, gdn_bufs: &GdnPrefillBuffers, batch_size: u32, cu_seqlens: DevicePtr, max_num_chunks: u32, total_nt: usize, max_seqlen: u32, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<bool>
cu_seqlens in
ONE gdn_prefill_fla(batch=N, is_varlen) call (replaces the non-uniform
per-request loop → fills chunk_delta_h’s 32→32N CTAs). Returns Ok(true)
if it ran, Ok(false) if not eligible (caller falls back to the loop).
Default (non-SSM layers, or FLA disabled): Ok(false).Source§fn prefill_phase3(
&self,
hidden: DevicePtr,
residual: DevicePtr,
num_tokens: usize,
gdn_bufs: &GdnPrefillBuffers,
token_offset: usize,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<()>
fn prefill_phase3( &self, hidden: DevicePtr, residual: DevicePtr, num_tokens: usize, gdn_bufs: &GdnPrefillBuffers, token_offset: usize, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<()>
Source§fn alloc_state(&self, gpu: &dyn GpuBackend) -> Result<Box<dyn LayerState>>
fn alloc_state(&self, gpu: &dyn GpuBackend) -> Result<Box<dyn LayerState>>
Source§fn uses_local_mla_prefill(&self) -> bool
fn uses_local_mla_prefill(&self) -> bool
Source§fn fp8_calibration_frozen(&self) -> Option<bool>
fn fp8_calibration_frozen(&self) -> Option<bool>
None = this layer runs no online calibration (non-attention layer,
static checkpoint scales, or a non-FP8 KV dtype). The scheduler’s
graph-suppression gate keys off this rather than a token count: the
scale freezes on the FIRST observe, so waiting calibration_tokens
tokens would run ~256+ eager steps for a calibration that finished
immediately.Source§fn decode_multi_seq_unsupported(&self) -> bool
fn decode_multi_seq_unsupported(&self) -> bool
decode_multi_seq’s shared-ForwardContext loop would alias
per-sequence state across rows rather than merely run slowly. Read moreSource§fn decode_verify_multi_unsupported(&self) -> bool
fn decode_verify_multi_unsupported(&self) -> bool
decode_verify_multi). Consumed by
can_batch_verify_dispatch; a true layer falls back to the
per-sequence verify loop, which is the sealed single-sequence path. Read moreSource§fn graph_stale_on_new_sequence(&self) -> bool
fn graph_stale_on_new_sequence(&self) -> bool
Source§fn sync_replayed_step(
&self,
_state: &mut dyn LayerState,
_seq_len: usize,
_k: usize,
) -> Result<()>
fn sync_replayed_step( &self, _state: &mut dyn LayerState, _seq_len: usize, _k: usize, ) -> Result<()>
seq_len is the
sequence length BEFORE this step’s k rows. Read moreSource§fn check_replay_room(
&self,
_state: &dyn LayerState,
_seq_len: usize,
_k: usize,
) -> Result<()>
fn check_replay_room( &self, _state: &dyn LayerState, _seq_len: usize, _k: usize, ) -> Result<()>
Source§fn prefill_inner_batched_q12(
&self,
_hidden_stacked: DevicePtr,
_residual_stacked: DevicePtr,
_num_tokens: usize,
_kv_cache: &mut PagedKvCache,
_seq_len_start: usize,
_batched_meta: &BatchedAttnMetadata,
_ctx: &ForwardContext<'_>,
_stream: u64,
) -> Result<()>
fn prefill_inner_batched_q12( &self, _hidden_stacked: DevicePtr, _residual_stacked: DevicePtr, _num_tokens: usize, _kv_cache: &mut PagedKvCache, _seq_len_start: usize, _batched_meta: &BatchedAttnMetadata, _ctx: &ForwardContext<'_>, _stream: u64, ) -> Result<()>
Source§fn transpose_moe_for_prefill(
&mut self,
_gpu: &dyn GpuBackend,
_config: &ModelConfig,
) -> Result<()>
fn transpose_moe_for_prefill( &mut self, _gpu: &dyn GpuBackend, _config: &ModelConfig, ) -> Result<()>
factory::build
after LM-head NVFP4 quantization has freed BF16 headroom, so
memory-tight EP configurations (e.g. MiniMax M2.7-NVFP4 EP=2) can
fit the transpose that layer-0 preflight would otherwise reject. Read moreSource§fn transpose_moe_gate_up_for_prefill(
&mut self,
_gpu: &dyn GpuBackend,
_config: &ModelConfig,
) -> Result<()>
fn transpose_moe_gate_up_for_prefill( &mut self, _gpu: &dyn GpuBackend, _config: &ModelConfig, ) -> Result<()>
transpose_moe_for_prefill but only transposes the gate+up
projections (skips the down projection), reducing the transpose cost
from 3× to 2× per expert. Used as a memory-tight fallback by the
MiniMax loader when full transpose doesn’t fit.Source§fn set_moe_down_transpose_scratch(
&mut self,
_scratch_packed: DevicePtr,
_scratch_scale: DevicePtr,
_packed_ptrs_t: DevicePtr,
_scale_ptrs_t: DevicePtr,
)
fn set_moe_down_transpose_scratch( &mut self, _scratch_packed: DevicePtr, _scratch_scale: DevicePtr, _packed_ptrs_t: DevicePtr, _scale_ptrs_t: DevicePtr, )
down_proj transpose scratch into this
layer’s MoE block. Used as a memory-tight alternative to the
persistent down transpose: factory allocates one shared scratch,
every MoE layer reuses it layer-by-layer during sequential
prefill. No-op for non-MoE layers and MoE layers that already
have a persistent transposed down.Source§fn transpose_moe_for_prefill_unified(
&mut self,
_gpu: &dyn GpuBackend,
_config: &ModelConfig,
) -> Result<()>
fn transpose_moe_for_prefill_unified( &mut self, _gpu: &dyn GpuBackend, _config: &ModelConfig, ) -> Result<()>
MoeLayer::use_t_layout_for_decode() must
gate dispatch to the _t decode kernels. Default no-op.