pub struct NllbGpuModel { /* private fields */ }Expand description
The served NLLB encoder-decoder model. Send + Sync: every field is either
immutable after construction or behind a Mutex; DevicePtr is a Copy
device handle and the GPU-side buffers are driven only through &self.
Implementations§
Source§impl NllbGpuModel
impl NllbGpuModel
Sourcepub fn new(
config: &ModelConfig,
store: &WeightStore,
gpu: Box<dyn GpuBackend>,
lang: NllbLang,
max_seq_len: usize,
max_batch: usize,
lora_dir: Option<&Path>,
) -> Result<Self>
pub fn new( config: &ModelConfig, store: &WeightStore, gpu: Box<dyn GpuBackend>, lang: NllbLang, max_seq_len: usize, max_batch: usize, lora_dir: Option<&Path>, ) -> Result<Self>
Build from the standard --model weight store + GPU backend. lang
carries the tokenizer-resolved source/target language ids (resolved
server-side, where the tokenizer lives). max_seq_len caps the decoder
KV depth.
Trait Implementations§
Source§impl Model for NllbGpuModel
impl Model for NllbGpuModel
Source§fn decode_batch(
&self,
tokens: &[u32],
seqs: &mut [&mut SequenceState],
_stream: u64,
) -> Result<DevicePtr>
fn decode_batch( &self, tokens: &[u32], seqs: &mut [&mut SequenceState], _stream: u64, ) -> Result<DevicePtr>
Batched decode: one forward_one per sequence into CONTIGUOUS logit rows
0..n (batch position i ↔ seqs[i]), the scheduler’s row contract.
Each sequence’s own per-slot KV is looked up by slot_idx, so batch
order is irrelevant. Sequences are processed serially on the default
stream (shared decode scratch); the returned base pointer is [n, vocab].
Source§fn prefill(
&self,
tokens: &[u32],
seq: &mut SequenceState,
_stream: u64,
) -> Result<DevicePtr>
fn prefill( &self, tokens: &[u32], seq: &mut SequenceState, _stream: u64, ) -> Result<DevicePtr>
Source§fn prefill_chunk(
&self,
tokens: &[u32],
seq: &mut SequenceState,
chunk_start: usize,
chunk_len: usize,
is_last_chunk: bool,
_stream: u64,
) -> Result<DevicePtr>
fn prefill_chunk( &self, tokens: &[u32], seq: &mut SequenceState, chunk_start: usize, chunk_len: usize, is_last_chunk: bool, _stream: u64, ) -> Result<DevicePtr>
chunk_len tokens starting at chunk_start in the prompt.
is_last_chunk runs final norm + LM head; intermediate chunks return
DevicePtr::NULL. KV blocks alloc incrementally; SSM state carries
across chunks; attention uses FA on chunk 0, paged decode after.Source§fn decode(
&self,
token: u32,
seq: &mut SequenceState,
_stream: u64,
) -> Result<DevicePtr>
fn decode( &self, token: u32, seq: &mut SequenceState, _stream: u64, ) -> Result<DevicePtr>
Source§fn vocab_size(&self) -> usize
fn vocab_size(&self) -> usize
Source§fn supports_beam(&self) -> bool
fn supports_beam(&self) -> bool
Self::generate_beam_batch). Default false — only encoder-decoder
translation models (NLLB) override it.Source§fn generate_beam_batch(&self, reqs: &[BeamReq]) -> Result<Vec<Vec<u32>>>
fn generate_beam_batch(&self, reqs: &[BeamReq]) -> Result<Vec<Vec<u32>>>
num_beams > 1 requests, bypassing the token-by-token decode
loop. Default: unsupported.Source§fn bind_gpu_to_thread(&self) -> Result<()>
fn bind_gpu_to_thread(&self) -> Result<()>
Source§fn alloc_sequence(&self) -> Result<SequenceState>
fn alloc_sequence(&self) -> Result<SequenceState>
Source§fn free_sequence(&self, seq: &mut SequenceState) -> Result<()>
fn free_sequence(&self, seq: &mut SequenceState) -> Result<()>
Source§fn compact_sequence(
&self,
seq: &mut SequenceState,
new_slot: usize,
) -> Result<()>
fn compact_sequence( &self, seq: &mut SequenceState, new_slot: usize, ) -> Result<()>
Source§fn detach_slot_for_reuse(&self, seq: &mut SequenceState)
fn detach_slot_for_reuse(&self, seq: &mut SequenceState)
compact_sequence
migrated it to a surviving sequence. Read moreSource§fn cache_sequence(&self, _seq: &SequenceState)
fn cache_sequence(&self, _seq: &SequenceState)
free_sequence() (block indices must still be
valid). Benefits multi-turn agentic sessions that resend full history.Source§fn num_free_blocks(&self) -> usize
fn num_free_blocks(&self) -> usize
Source§fn copy_logits_to_host(
&self,
logits_ptr: DevicePtr,
dst: &mut [u8],
) -> Result<()>
fn copy_logits_to_host( &self, logits_ptr: DevicePtr, dst: &mut [u8], ) -> Result<()>
Source§fn logits_buffer_ptr(&self) -> DevicePtr
fn logits_buffer_ptr(&self) -> DevicePtr
[k, vocab] BF16 after
decode_verify_graphed). Lets the scheduler read logits for temp
sampling even though graphs bake in argmax.Source§fn argmax_on_device(&self, logits_ptr: DevicePtr, _stream: u64) -> Result<u32>
fn argmax_on_device(&self, logits_ptr: DevicePtr, _stream: u64) -> Result<u32>
Source§fn argmax_batch(
&self,
logits_ptr: DevicePtr,
n: usize,
_stream: u64,
) -> Result<Vec<u32>>
fn argmax_batch( &self, logits_ptr: DevicePtr, n: usize, _stream: u64, ) -> Result<Vec<u32>>
[N, vocab] BF16; returns N token IDs.Source§fn decode_verify(
&self,
_t: &[u32],
_s: &mut SequenceState,
_st: u64,
) -> Result<Vec<u32>>
fn decode_verify( &self, _t: &[u32], _s: &mut SequenceState, _st: u64, ) -> Result<Vec<u32>>
Source§fn checkpoint_ssm_states(&self, _seq: &mut SequenceState) -> Result<()>
fn checkpoint_ssm_states(&self, _seq: &mut SequenceState) -> Result<()>
Source§fn rollback_ssm_states(&self, _seq: &mut SequenceState, _n: usize) -> Result<()>
fn rollback_ssm_states(&self, _seq: &mut SequenceState, _n: usize) -> Result<()>
Source§fn generate_speculative(
&self,
_tokens: &[u32],
_params: &SamplingParams,
_num_drafts: usize,
) -> Result<GenerateResult>
fn generate_speculative( &self, _tokens: &[u32], _params: &SamplingParams, _num_drafts: usize, ) -> Result<GenerateResult>
Source§fn has_proposer(&self) -> bool
fn has_proposer(&self) -> bool
Source§fn has_self_speculative(&self) -> bool
fn has_self_speculative(&self) -> bool
Source§fn decode_draft(
&self,
_token: u32,
_seq: &mut SequenceState,
_stream: u64,
) -> Result<DevicePtr>
fn decode_draft( &self, _token: u32, _seq: &mut SequenceState, _stream: u64, ) -> Result<DevicePtr>
Source§fn decode_verify_graphed(
&self,
_t: &[u32; 2],
_s: &mut SequenceState,
_st: u64,
) -> Result<[u32; 2]>
fn decode_verify_graphed( &self, _t: &[u32; 2], _s: &mut SequenceState, _st: u64, ) -> Result<[u32; 2]>
[verified_0, verified_1] argmax IDs. SSM intermediates saved for
partial rollback via rollback_ssm_states.Source§fn decode_verify_graphed_k3(
&self,
_t: &[u32; 3],
_s: &mut SequenceState,
_st: u64,
) -> Result<[u32; 3]>
fn decode_verify_graphed_k3( &self, _t: &[u32; 3], _s: &mut SequenceState, _st: u64, ) -> Result<[u32; 3]>
[0] and [1] are saved for partial rollback.Source§fn decode_verify_graphed_k4(
&self,
_t: &[u32; 4],
_s: &mut SequenceState,
_st: u64,
) -> Result<[u32; 4]>
fn decode_verify_graphed_k4( &self, _t: &[u32; 4], _s: &mut SequenceState, _st: u64, ) -> Result<[u32; 4]>
token_idx (0 or 1) to a
dedicated MTP input buffer. Must precede run_mtp_propose — MTP
overwrites shared buffers including norm_output.Source§fn run_mtp_propose(
&self,
_token: u32,
_position: usize,
_seq: &mut SequenceState,
_stream: u64,
) -> Result<Option<u32>>
fn run_mtp_propose( &self, _token: u32, _position: usize, _seq: &mut SequenceState, _stream: u64, ) -> Result<Option<u32>>
None when no proposer is wired.Source§fn run_mtp_propose_multi(
&self,
_token: u32,
_position: usize,
_num_drafts: usize,
_seq: &mut SequenceState,
_stream: u64,
_grammar_bitmask: Option<&[i32]>,
) -> Result<Vec<u32>>
fn run_mtp_propose_multi( &self, _token: u32, _position: usize, _num_drafts: usize, _seq: &mut SequenceState, _stream: u64, _grammar_bitmask: Option<&[i32]>, ) -> Result<Vec<u32>>
Source§fn trim_proposer_state(
&self,
_seq: &mut SequenceState,
_num_accepted: usize,
_stream: u64,
) -> Result<()>
fn trim_proposer_state( &self, _seq: &mut SequenceState, _num_accepted: usize, _stream: u64, ) -> Result<()>
Source§fn teardown(&mut self) -> Result<()>
fn teardown(&mut self) -> Result<()>
Source§fn poll_innerq(&self)
fn poll_innerq(&self)
OnceLock for this, which meant
the driver could outlive the model whose device symbols it writes.Source§fn mixed_forward(
&self,
decode_tokens: &[u32],
decode_seqs: &mut [&mut SequenceState],
prefill_tokens: &[u32],
prefill_seq: &mut SequenceState,
prefill_chunk_start: usize,
prefill_chunk_len: usize,
prefill_is_last: bool,
stream: u64,
) -> Result<MixedForwardResult>
fn mixed_forward( &self, decode_tokens: &[u32], decode_seqs: &mut [&mut SequenceState], prefill_tokens: &[u32], prefill_seq: &mut SequenceState, prefill_chunk_start: usize, prefill_chunk_len: usize, prefill_is_last: bool, stream: u64, ) -> Result<MixedForwardResult>
[N, vocab] and prefill
logits [1, vocab] (when is_last). Default: serial decode + prefill.Source§fn prefill_batch_chunk(
&self,
streams: &mut [PrefillSlice<'_>],
stream: u64,
) -> Result<Vec<DevicePtr>>
fn prefill_batch_chunk( &self, streams: &mut [PrefillSlice<'_>], stream: u64, ) -> Result<Vec<DevicePtr>>
prefill_chunk — implementors that
support kernel-level batched prefill should override this. Read moreSource§fn prefill_batch_chunk_rows(
&self,
streams: &mut [PrefillSlice<'_>],
stream: u64,
_row_base: usize,
) -> Result<Vec<DevicePtr>>
fn prefill_batch_chunk_rows( &self, streams: &mut [PrefillSlice<'_>], stream: u64, _row_base: usize, ) -> Result<Vec<DevicePtr>>
prefill_batch_chunk, but each finishing stream’s first-token
logits land in row row_base + stream_idx of the shared logits arena
instead of row stream_idx. Read moreSource§fn mixed_forward_batch(
&self,
decode_tokens: &[u32],
decode_seqs: &mut [&mut SequenceState],
prefill_streams: &mut [PrefillSlice<'_>],
stream: u64,
) -> Result<MixedBatchResult>
fn mixed_forward_batch( &self, decode_tokens: &[u32], decode_seqs: &mut [&mut SequenceState], prefill_streams: &mut [PrefillSlice<'_>], stream: u64, ) -> Result<MixedBatchResult>
decode_batch + prefill_batch_chunk serially. Models that
implement true mixed batching should override.Source§fn normalize_ssm_states(&self, _seq: &SequenceState, _stream: u64) -> Result<()>
fn normalize_ssm_states(&self, _seq: &SequenceState, _stream: u64) -> Result<()>
Source§fn prefill_twophase(
&self,
tokens: &[u32],
seq: &mut SequenceState,
_chunk_size: usize,
stream: u64,
) -> Result<DevicePtr>
fn prefill_twophase( &self, tokens: &[u32], seq: &mut SequenceState, _chunk_size: usize, stream: u64, ) -> Result<DevicePtr>
Source§fn set_active_lora(&mut self, _name: &str) -> Result<()>
fn set_active_lora(&mut self, _name: &str) -> Result<()>
name
as active (re-points the delta pool pointers). MUST be called at a
scheduler quiescent point (no in-flight decode). Graph-safety is via the
eager-on-rotate gate. Default: unsupported (non-LoRA or non-rotatable).Source§fn adapter_id_for(&self, _slot: i32) -> u64
fn adapter_id_for(&self, _slot: i32) -> u64
slot follows SequenceState.adapter_slot: >= 0
picks that resident slot, -1 defers to the installed active adapter.
The default (no LoRA) returns the base sentinel 0, keeping the prefix
cache byte-identical to the pre-LoRA path.Source§fn acquire_adapter_slot(&self, _slot: i32) -> i32
fn acquire_adapter_slot(&self, _slot: i32) -> i32
-1 -> active like Self::adapter_id_for.
Returns the RESOLVED pool index the ref was taken on (store it, release
EXACTLY that index at terminal free — immune to a rotate changing active).
Default (no LoRA) returns -1 “nothing acquired” so the release guard
skips and the base path is byte-identical.Source§fn release_adapter_slot(&self, _resolved: i32)
fn release_adapter_slot(&self, _resolved: i32)
Self::acquire_adapter_slot,
by the RESOLVED index it returned. -1 is a no-op. Default: no-op.Source§fn swap_lora_from_disk(
&mut self,
_dir: &Path,
_name: &str,
_slot: usize,
) -> Result<()>
fn swap_lora_from_disk( &mut self, _dir: &Path, _name: &str, _slot: usize, ) -> Result<()>
dir INTO pool
slot and make it resident there (pool-size-1 per-request weight change).
MUST be called at a scheduler quiescent point; needs rotation armed.
Default: unsupported (non-LoRA or non-rotatable).Source§fn promote_lora_from_peer(
&mut self,
_peer_addr: &str,
_adapter_id: &str,
_name: &str,
_peft: PeftAdapterConfig,
) -> Result<(usize, Option<String>)>
fn promote_lora_from_peer( &mut self, _peer_addr: &str, _adapter_id: &str, _name: &str, _peft: PeftAdapterConfig, ) -> Result<(usize, Option<String>)>
name
(staged on peer_addr at adapter_id) from the peer into a cache pool
slot and make it active, returning (slot, evicted_name). Runs at a
scheduler quiescent point. peft supplies the r/alpha/scaling the peer
manifest does not carry. Default: unsupported (non-LoRA / non-cuda).Source§fn promote_lora_from_disk(
&mut self,
_adapter_dir: &Path,
_name: &str,
) -> Result<(usize, Option<String>)>
fn promote_lora_from_disk( &mut self, _adapter_dir: &Path, _name: &str, ) -> Result<(usize, Option<String>)>
name from
adapter_dir into a cache pool slot (LRU victim) and make it active,
returning (slot, evicted_name). Local-disk sibling of
Self::promote_lora_from_peer; the swap re-parses the dir’s
adapter_config.json, so no peft arg. Runs at a scheduler quiescent
point; needs rotation armed. Default: unsupported.Source§fn high_speed_swap_dims(&self) -> Option<ModelDims>
fn high_speed_swap_dims(&self) -> Option<ModelDims>
--high-speed-swap orchestrator (installed thread-local
after bind_gpu_to_thread). None for legacy/non-attention models.Source§fn alloc_sequence_for(&self, budget_tokens: usize) -> Result<SequenceState>
fn alloc_sequence_for(&self, budget_tokens: usize) -> Result<SequenceState>
Self::alloc_sequence told what this request can actually reach
(prompt_len + max_tokens). Proposer state that scales with context is
sized to THAT instead of --max-seq-len; see
DraftProposer::alloc_state_for. Defaults to the unsized form.Source§fn logits_ptr_is_fp32(&self, _logits_ptr: DevicePtr) -> bool
fn logits_ptr_is_fp32(&self, _logits_ptr: DevicePtr) -> bool
vocab*4 bytes, reinterpret &[f32]).
True only for Gemma-4 dense single-token decode lm_head; default false.Source§fn has_ssm_layers(&self) -> bool
fn has_ssm_layers(&self) -> bool
h_state + conv_state are advanced in-place every decoded
token. Read moreSource§fn mtp_slot_draft_capacity(&self, _slot_idx: usize) -> usize
fn mtp_slot_draft_capacity(&self, _slot_idx: usize) -> usize
slot_idx — the deepest num_drafts a
speculative step may dispatch to it without overflowing its slot’s
per-token H-intermediate allocation (tiered since 2026-08-16; SSOT
ssm_reserve::verify_slot_h_intermediates). The scheduler clamps
every spec step’s draft count to the MINIMUM capacity across the
active slots. Default usize::MAX: no SSM verify pools to
constrain (pure-attention models, spec off).Source§fn decode_rollback_ring_slots(&self) -> usize
fn decode_rollback_ring_slots(&self) -> usize
0 (the default) means the
model keeps no decode-rollback snapshots — appropriate for
pure-attention models and for SSM models when the snapshot pool
has no capacity reserved. SSM models with a populated pool
override to ROLLBACK_RESTEER_CAP + 1.Source§fn save_decode_ssm_snapshot(
&self,
_seq: &SequenceState,
_ring_slot: usize,
) -> Result<()>
fn save_decode_ssm_snapshot( &self, _seq: &SequenceState, _ring_slot: usize, ) -> Result<()>
seq’s live SSM h_state + conv_state (all SSM layers)
into the decode-rollback snapshot slot ring_slot. Read moreSource§fn restore_decode_ssm_snapshot(
&self,
_seq: &SequenceState,
_ring_slot: usize,
) -> Result<()>
fn restore_decode_ssm_snapshot( &self, _seq: &SequenceState, _ring_slot: usize, ) -> Result<()>
seq’s SSM h_state + conv_state (all SSM layers)
from the decode-rollback snapshot slot ring_slot previously
written by Self::save_decode_ssm_snapshot. Read moreSource§fn dflash_gamma(&self) -> Option<usize>
fn dflash_gamma(&self) -> Option<usize>
num_drafts = γ - 1 from THIS (the head is
the SSOT — it resolved the drafter config’s trained block size),
never from a CLI default that may not match the checkpoint.Source§fn decode_marconi_checkpoint(&self, _seq: &mut SequenceState)
fn decode_marconi_checkpoint(&self, _seq: &mut SequenceState)
Source§fn can_batch_verify(&self, _ks: &[usize]) -> bool
fn can_batch_verify(&self, _ks: &[usize]) -> bool
Self::decode_verify_batched can run for ks.len()
sequences at ks[i] verify rows each (one more than that sequence’s
draft count; the K-vs-batch ladder passes 2..=4, and D-Cut makes the
vector RAGGED — uniform is just the special case). Read moreSource§fn decode_verify_batched(
&self,
tokens: &[u32],
ks: &[usize],
seqs: &mut [&mut SequenceState],
stream: u64,
) -> Result<Vec<u32>>
fn decode_verify_batched( &self, tokens: &[u32], ks: &[usize], seqs: &mut [&mut SequenceState], stream: u64, ) -> Result<Vec<u32>>
ks.len() sequences × ks[i] rows in ONE eager
forward (flat seq-major rows, tokens.len() == Σ ks). Weight matrices
are read once for all Σ ks rows. Sequence i occupies rows
[off_i, off_i + ks[i]) where off_i = Σ_{t<i} ks[t], holding
[last_verified, d0, .., d_{ks[i]-2}]. Returns the Σ ks argmax IDs
in the same flat order. On success each sequence’s tokens/seq_len
advance by its own ks[i] (rewind is the caller’s verdict arithmetic,
same as the per-seq path). On Err NO sequence state has been advanced. Read morerows[i] of the just-run batched verify forward
into stash slot i (verify_hidden_stash), BEFORE any propose
clobbers the shared hidden_states buffer. Companion of
Self::decode_verify_batched.Self::save_hidden_for_mtp: copy stash slot
idx (written by Self::stash_verify_hidden_rows) into the MTP
input buffer. Used by the batched-verify verdict path, whose propose
calls have already overwritten the live verify rows.Source§fn run_mtp_propose_batched(
&self,
tokens: &[u32],
positions: &[usize],
stash_idx: &[usize],
num_drafts: usize,
seqs: &mut [&mut SequenceState],
stream: u64,
out_conf: Option<&mut Vec<Vec<f32>>>,
) -> Result<Option<Vec<Vec<u32>>>>
fn run_mtp_propose_batched( &self, tokens: &[u32], positions: &[usize], stash_idx: &[usize], num_drafts: usize, seqs: &mut [&mut SequenceState], stream: u64, out_conf: Option<&mut Vec<Vec<f32>>>, ) -> Result<Option<Vec<Vec<u32>>>>
num_drafts drafts for each of tokens.len() sequences, reading
every drafter weight once per draft position instead of once per
sequence. stash_idx[i] names the verify-stash slot holding sequence
i’s accepted-position hidden (written by
Self::stash_verify_hidden_rows); positions[i] is the propose
position (post-rewind seq_len), matching the per-seq
Self::run_mtp_propose_multi contract. Grammarless sequences only. Read moreSource§fn mtp_propose_batch_max(&self) -> usize
fn mtp_propose_batch_max(&self) -> usize
Self::run_mtp_propose_batched can carry in ONE
drafter forward per draft position. 1 = per-sequence only.
Schedulers chunk their propose groups by this — never by a constant.Source§fn decode_verify_graphed_kgamma(
&self,
tokens: &[u32],
seq: &mut SequenceState,
stream: u64,
) -> Result<Vec<u32>>
fn decode_verify_graphed_kgamma( &self, tokens: &[u32], seq: &mut SequenceState, stream: u64, ) -> Result<Vec<u32>>
decode_verify. Models can override for CUDA-graph speedup keyed by
(slot_idx, K).Source§fn decode_verify_dflash(
&self,
tokens: &[u32],
seq: &mut SequenceState,
stream: u64,
) -> Result<Vec<u32>>
fn decode_verify_dflash( &self, tokens: &[u32], seq: &mut SequenceState, stream: u64, ) -> Result<Vec<u32>>
(slot_idx, tokens.len()).
Default routes to decode_verify_graphed_kgamma.Source§fn decode_and_verify_fused(
&self,
tokens: &[u32],
seq: &mut SequenceState,
stream: u64,
) -> Result<Vec<u32>>
fn decode_and_verify_fused( &self, tokens: &[u32], seq: &mut SequenceState, stream: u64, ) -> Result<Vec<u32>>
pos for the drafter catch-up feed. Default no-op.hidden_states[token_idx] from every DFlash capture layer
into dflash_hidden_save. Called after gamma verify Phase 3 D2H
sync (bonus position known). No-op when DFlash is disabled.Source§fn dflash_accept_append(&self, _seq: &mut SequenceState) -> Result<()>
fn dflash_accept_append(&self, _seq: &mut SequenceState) -> Result<()>
Source§fn dflash_eagle_accept_append(&self, _seq: &mut SequenceState) -> Result<()>
fn dflash_eagle_accept_append(&self, _seq: &mut SequenceState) -> Result<()>
Source§fn dflash_eagle_kgamma_append(
&self,
_seq: &mut SequenceState,
_num_accepted: usize,
_base_pos: usize,
) -> Result<()>
fn dflash_eagle_kgamma_append( &self, _seq: &mut SequenceState, _num_accepted: usize, _base_pos: usize, ) -> Result<()>
Source§fn dflash_serial_ctx_append(&self, _seq: &mut SequenceState) -> Result<()>
fn dflash_serial_ctx_append(&self, _seq: &mut SequenceState) -> Result<()>
dflash_hidden_save row 0, filled by
try_dflash_capture inside the decode layer loop) into the seq’s
DFlash ctx accumulator, stamped at its true position
(seq.seq_len - 1, matching propose.rs’s decode-append convention). Read moreSource§fn commit_ctx(
&self,
_seq: &mut SequenceState,
_num_committed: usize,
_base_pos: usize,
_scratch_row: usize,
) -> Result<()>
fn commit_ctx( &self, _seq: &mut SequenceState, _num_committed: usize, _base_pos: usize, _scratch_row: usize, ) -> Result<()>
num_committed scratch rows (dflash_hidden_save rows
scratch_row..scratch_row+num_committed) into ctx_hidden_acc at the
CURRENT TAIL (ctx_len), stamping RoPE positions
base_pos..base_pos+num_committed, folding the watermark slide in
first. base_pos is the RoPE position, NOT the acc row index (they
diverge after a watermark slide — DDD §4.1 landmine). scratch_row is
0 on every single-sequence path; batched decode (n>1) captures ALL
batch rows, so seq i commits from scratch row i. The single structural
replacement for the ~5 fragmented appends. Default no-op for models
without a DFlash drafter.Source§fn dflash_capture_band(&self) -> usize
fn dflash_capture_band(&self) -> usize
i of a batched K=γ verify captures into band i, so its
commit_ctx scratch_row is i * dflash_capture_band(). Returning
the model’s own stride keeps the capture and the commit from ever
disagreeing. 0 when there is no DFlash drafter.Source§fn read_deferred_draft_token(&self) -> Result<u32>
fn read_deferred_draft_token(&self) -> Result<u32>
run_mtp_propose_multi
call (which used embed_from_argmax to write the draft embedding and
token ID directly on GPU). Returns 0 if no proposer is available.Source§fn prepare_vision_embed(&self, _images: &[VisionItem]) -> Result<()>
fn prepare_vision_embed(&self, _images: &[VisionItem]) -> Result<()>
Source§fn prepare_vision_embed_batched(
&self,
_per_request: &[Vec<VisionItem>],
) -> Result<Vec<(usize, usize, usize, usize)>>
fn prepare_vision_embed_batched( &self, _per_request: &[Vec<VisionItem>], ) -> Result<Vec<(usize, usize, usize, usize)>>
forward_batched
call (block GEMM weights read once over Σpatches). per_request[i] is
request i’s images. Returns one (patch_row_offset, grid_index_offset, num_images, patch_row_count) per request, in request order, locating
its slice of the shared packed buf_out. Default: no-op (text models).Source§fn set_vision_slice_base(
&self,
_row_base: usize,
_grid_base: usize,
_owned_images: usize,
)
fn set_vision_slice_base( &self, _row_base: usize, _grid_base: usize, _owned_images: usize, )
Source§fn ep_worker_step(&self, _slots: &mut [Option<SequenceState>]) -> Result<bool>
fn ep_worker_step(&self, _slots: &mut [Option<SequenceState>]) -> Result<bool>
Source§fn is_ep(&self) -> bool
fn is_ep(&self) -> bool
Source§fn decode_logits_fp32(&self) -> bool
fn decode_logits_fp32(&self) -> bool
lm_head writes FP32 logits to a
dedicated FP32 scratch buffer (rather than the shared BF16 logits
buffer). Callers that consume those logits must read from
Self::decode_logits_ptr using 4 bytes/element. Defaults false;
only Gemma-4 dense overrides today (gated by
ATLAS_GEMMA4_FP32_LMHEAD=1).Source§fn decode_logits_ptr(&self) -> DevicePtr
fn decode_logits_ptr(&self) -> DevicePtr
lm_head last wrote to. The
returned dtype is FP32 when Self::decode_logits_fp32 is true,
BF16 otherwise. The default impl returns the shared BF16 logits
buffer used by every existing model. Override on models that route
the lm_head output through an FP32 scratch (Gemma-4 + softcap).Source§fn is_mla(&self) -> bool
fn is_mla(&self) -> bool
Source§fn hc_mult(&self) -> usize
fn hc_mult(&self) -> usize
qwen3_ssm::hc::refuse_batched_under_hc); the scheduler must clamp
concurrency to 1 until the batched highway lands (Avarok #753 item B).Source§fn kv_block_size(&self) -> Option<usize>
fn kv_block_size(&self) -> Option<usize>
None when the model has no paged KV.
The scheduler uses this to land a prefill chunk boundary exactly on the
block boundary a warm turn will match at (see
spark_runtime::ssm_tail_boundary).Source§fn ep_broadcast_cmd(&self, _cmd: u32) -> Result<()>
fn ep_broadcast_cmd(&self, _cmd: u32) -> Result<()>
Source§fn ep_broadcast_cmd_for_seq(&self, _seq_id: u32, _cmd: u32) -> Result<()>
fn ep_broadcast_cmd_for_seq(&self, _seq_id: u32, _cmd: u32) -> Result<()>
(seq_id, cmd) pair to all worker ranks. Read moreSource§fn ep_protocol_v2(&self) -> bool
fn ep_protocol_v2(&self) -> bool
Source§fn ep_broadcast_tokens(&self, _tokens: &[u32]) -> Result<Vec<u32>>
fn ep_broadcast_tokens(&self, _tokens: &[u32]) -> Result<Vec<u32>>
Source§fn start_checkpoint_async(&self, seq: &mut SequenceState) -> Result<()>
fn start_checkpoint_async(&self, seq: &mut SequenceState) -> Result<()>
Source§fn start_rollback_and_checkpoint_async(
&self,
seq: &mut SequenceState,
num_accepted: usize,
) -> Result<()>
fn start_rollback_and_checkpoint_async( &self, seq: &mut SequenceState, num_accepted: usize, ) -> Result<()>
Source§fn sync_secondary(&self) -> Result<()>
fn sync_secondary(&self) -> Result<()>
Source§fn commit_accepted_prefix(
&self,
_seq: &mut SequenceState,
_num_accepted: usize,
_k: usize,
) -> Result<()>
fn commit_accepted_prefix( &self, _seq: &mut SequenceState, _num_accepted: usize, _k: usize, ) -> Result<()>
h_state /
conv_state. Full accept (num_accepted == k) is a no-op (the
kernel’s final state is already live); partial accept is a single
index-select of h_state_intermediates[num_accepted-1]. No-op
default for backends without the dual-buffer SSM state.
Runs on secondary_stream; pair with sync_secondary.Source§fn save_sequence_state(
&self,
_seq: &SequenceState,
_writer: &mut dyn Write,
) -> Result<()>
fn save_sequence_state( &self, _seq: &SequenceState, _writer: &mut dyn Write, ) -> Result<()>
Source§fn restore_sequence_state(
&self,
_seq: &mut SequenceState,
_num_blocks: usize,
_reader: &mut dyn Read,
) -> Result<()>
fn restore_sequence_state( &self, _seq: &mut SequenceState, _num_blocks: usize, _reader: &mut dyn Read, ) -> Result<()>
Source§fn tokens_contain_vision_pad(&self, _tokens: &[u32]) -> bool
fn tokens_contain_vision_pad(&self, _tokens: &[u32]) -> bool
tokens contains a vision pad token for this model — i.e.
the KV at those positions came from image/video EMBEDDINGS that a
plain token re-prefill cannot reproduce. Decode-time preemption uses
this to exclude vision sequences from the requeue-with-re-prefill
path (the spill path, which saves KV verbatim, stays eligible).
Default false: pure-text models are always re-prefillable.Source§fn num_total_blocks(&self) -> usize
fn num_total_blocks(&self) -> usize
Source§fn reclaim_prefix_blocks(&self, _num_blocks: usize) -> usize
fn reclaim_prefix_blocks(&self, _num_blocks: usize) -> usize
num_blocks blocks from the prefix cache, returning how
many actually became free. Read moreSource§fn default_stream(&self) -> u64
fn default_stream(&self) -> u64
Source§fn create_stream(&self) -> Result<u64>
fn create_stream(&self) -> Result<u64>
Source§fn create_event(&self) -> Result<u64>
fn create_event(&self) -> Result<u64>
Source§fn record_event(&self, _event: u64, _stream: u64) -> Result<()>
fn record_event(&self, _event: u64, _stream: u64) -> Result<()>
Source§fn stream_wait_event(&self, _stream: u64, _event: u64) -> Result<()>
fn stream_wait_event(&self, _stream: u64, _event: u64) -> Result<()>
Source§fn synchronize(&self, _stream: u64) -> Result<()>
fn synchronize(&self, _stream: u64) -> Result<()>
stream has completed.
Used by mixed_forward_batch to retire the decode pass (which runs on
the default stream) before the batched prefill reuses the shared arena
buffers on another stream (#110). Default no-op for non-CUDA mocks.