pub struct MtpHead { /* private fields */ }Expand description
MTP prediction head.
Implementations§
Source§impl MtpHead
impl MtpHead
pub fn new( weights: MtpWeights, embed_tokens: DenseWeight, lm_head_nvfp4: QuantizedWeight, lm_head_nvfp4_t: Option<(QuantizedWeight, u32)>, config: &ModelConfig, gpu: &dyn GpuBackend, quant: MtpQuantization, mtp_vocab_size: u32, max_seq_len: usize, main_kv_blocks: usize, levers: &ModelLevers, ) -> Result<Self>
Trait Implementations§
Source§impl DraftProposer for MtpHead
impl DraftProposer for MtpHead
Source§fn last_confidence(&self) -> Option<f32>
fn last_confidence(&self) -> Option<f32>
★ The one draft_conf_tau reader that KEEPS its environment read.
Its three siblings were asked per propose whether the feature was on,
so they paid the process-wide environment lock only to learn it was
off. This one is different: run_mtp_propose_inner already gates on
tau > 0.0 before calling it, so this read happens only when the
feature is ARMED — which is never on a shipped config, since the
clamp is staged off. Routing it through ModelLevers would mean
widening a DraftProposer trait method to carry levers for a read
that costs nothing in production.
The check stays because it is this method’s own contract — None
means “no confidence is being tracked” — and a future caller must not
have to know that run_mtp_propose_inner checked first.
Source§fn alloc_state(&self, _gpu: &dyn GpuBackend) -> Result<Box<dyn ProposerState>>
fn alloc_state(&self, _gpu: &dyn GpuBackend) -> Result<Box<dyn ProposerState>>
Source§fn propose(
&self,
last_token: u32,
target_hidden: DevicePtr,
position: usize,
num_drafts: usize,
state: &mut dyn ProposerState,
ctx: &ForwardContext<'_>,
stream: u64,
draft_embed_target: Option<DevicePtr>,
grammar_bitmask: Option<&[i32]>,
_target_hidden_stack: Option<DevicePtr>,
) -> Result<Vec<u32>>
fn propose( &self, last_token: u32, target_hidden: DevicePtr, position: usize, num_drafts: usize, state: &mut dyn ProposerState, ctx: &ForwardContext<'_>, stream: u64, draft_embed_target: Option<DevicePtr>, grammar_bitmask: Option<&[i32]>, _target_hidden_stack: Option<DevicePtr>, ) -> Result<Vec<u32>>
num_drafts tokens autoregressively. Read moreSource§fn propose_batch(
&self,
last_tokens: &[u32],
target_hiddens: &[DevicePtr],
positions: &[usize],
num_drafts: usize,
states: &mut [&mut dyn ProposerState],
ctx: &ForwardContext<'_>,
stream: u64,
out_conf: Option<&mut Vec<Vec<f32>>>,
) -> Result<Option<Vec<Vec<u32>>>>
fn propose_batch( &self, last_tokens: &[u32], target_hiddens: &[DevicePtr], positions: &[usize], num_drafts: usize, states: &mut [&mut dyn ProposerState], ctx: &ForwardContext<'_>, stream: u64, out_conf: Option<&mut Vec<Vec<f32>>>, ) -> Result<Option<Vec<Vec<u32>>>>
num_drafts tokens for each of
n = last_tokens.len() sequences, reading every drafter weight ONCE
per draft position instead of once per sequence (the measured C=4
serialization: 12 x ~5 ms per-seq drafter forwards per batched verify
step, ~62 ms of the ~180 ms step). Read moreSource§fn propose_batch_max(
&self,
buffers: &BufferArena,
config: &ModelConfig,
) -> usize
fn propose_batch_max( &self, buffers: &BufferArena, config: &ModelConfig, ) -> usize
Self::propose_batch can carry in ONE drafter
forward per draft position, derived from this proposer’s resolved
kernels and the arena’s row capacities. 1 = per-sequence only. Read moreSource§fn prefill_drafter(
&self,
prompt_tokens: &[u32],
hiddens: DevicePtr,
state: &mut dyn ProposerState,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<usize>
fn prefill_drafter( &self, prompt_tokens: &[u32], hiddens: DevicePtr, state: &mut dyn ProposerState, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<usize>
propose() of a sequence (ATLAS_MTP_DRAFTER_PREFILL). Read moreSource§fn drafter_rows(&self, state: &mut dyn ProposerState) -> usize
fn drafter_rows(&self, state: &mut dyn ProposerState) -> usize
Source§fn last_pair_key(&self, state: &mut dyn ProposerState) -> Option<usize>
fn last_pair_key(&self, state: &mut dyn ProposerState) -> Option<usize>
None = untracked;
catch-up is skipped). The drafter row space is compacted, so rows
cannot locate the drafter in the sequence — this can.Source§fn take_drafter_kv(
&self,
state: &mut dyn ProposerState,
) -> Option<(Vec<u32>, usize, Option<usize>)>
fn take_drafter_kv( &self, state: &mut dyn ProposerState, ) -> Option<(Vec<u32>, usize, Option<usize>)>
free_state releases nothing and the model can
hold them for the next turn. Returns (blocks, rows, last_pair_key);
None = unsupported or nothing to carry. After this call the state
must behave as if freshly allocated.Source§fn install_drafter_kv(
&self,
state: &mut dyn ProposerState,
blocks: Vec<u32>,
rows: usize,
last_pair_key: Option<usize>,
) -> bool
fn install_drafter_kv( &self, state: &mut dyn ProposerState, blocks: Vec<u32>, rows: usize, last_pair_key: Option<usize>, ) -> bool
Self::take_drafter_kv: install carried blocks into a fresh
proposer state. Returns false when unsupported (caller must then free
the blocks itself).Source§fn free_drafter_kv(&self, blocks: &[u32])
fn free_drafter_kv(&self, blocks: &[u32])
Source§fn catchup_drafter(
&self,
tokens: &[u32],
hiddens: DevicePtr,
row_base: usize,
pos_base: usize,
state: &mut dyn ProposerState,
ctx: &ForwardContext<'_>,
stream: u64,
) -> Result<usize>
fn catchup_drafter( &self, tokens: &[u32], hiddens: DevicePtr, row_base: usize, pos_base: usize, state: &mut dyn ProposerState, ctx: &ForwardContext<'_>, stream: u64, ) -> Result<usize>
row_base .. with RoPE positions
pos_base .. from (tokens, hiddens) pairs — the catch-up feed.
Returns rows written (0 = unsupported/no-op).Source§fn read_deferred_draft_token(&self, gpu: &dyn GpuBackend) -> Result<u32>
fn read_deferred_draft_token(&self, gpu: &dyn GpuBackend) -> Result<u32>
propose() call
that used draft_embed_target = Some(...). Returns 0 if not supported.Source§fn after_verify(
&self,
num_accepted: usize,
state: &mut dyn ProposerState,
_stream: u64,
) -> Result<()>
fn after_verify( &self, num_accepted: usize, state: &mut dyn ProposerState, _stream: u64, ) -> Result<()>
Source§fn free_state(
&self,
_gpu: &dyn GpuBackend,
state: &mut dyn ProposerState,
) -> Result<()>
fn free_state( &self, _gpu: &dyn GpuBackend, state: &mut dyn ProposerState, ) -> Result<()>
Source§fn alloc_state_for(
&self,
gpu: &dyn GpuBackend,
budget_tokens: usize,
) -> Result<Box<dyn ProposerState>>
fn alloc_state_for( &self, gpu: &dyn GpuBackend, budget_tokens: usize, ) -> Result<Box<dyn ProposerState>>
Self::alloc_state with the sequence’s KNOWN token budget
(prompt_len + max_tokens), so a proposer whose per-sequence state
scales with context can size to what this request can actually reach
instead of the global --max-seq-len ceiling. That distinction is what
OOMs a high-concurrency long-context serve: the ceiling is per-sequence
and paid n times, while a typical request needs a fraction of it. Read moreSource§fn block_gamma(&self) -> Option<usize>
fn block_gamma(&self) -> Option<usize>
None = not a block drafter.mtp_prefill_hidden, given
the served --max-seq-len. Read moreSource§fn needs_comm(&self) -> bool
fn needs_comm(&self) -> bool
o_proj reduce), like any target layer. Read morectx.buffers), so it must not run from the end-of-prefill
eager hook — only from the first propose, where the target owns
nothing. Read more