BufferArena

Struct BufferArena 

Source
pub struct BufferArena { /* private fields */ }
Expand description

2026-09-25: The GPU buffers of one forward pass, M = max_batch_tokens. BufferSizes::from_config holds each buffer’s size formula.

Implementations§

Source§

impl BufferArena

Source

pub fn hidden_states(&self) -> DevicePtr

Source

pub fn residual(&self) -> DevicePtr

Source

pub fn norm_output(&self) -> DevicePtr

Source

pub fn norm_output_bytes(&self) -> usize

2026-09-25: Allocated byte size of norm_output, the bound the attention prefill o_proj’s cuBLASLt arm (paged_oproj.rs) checks its ceil16(M) rows against.

Source

pub fn qkv_output(&self) -> DevicePtr

Source

pub fn qkv_output_bytes(&self) -> usize

2026-09-25: Allocated byte size of qkv_output, the bound the multi-seq decode W8A8 arm (multi_seq/w8a8_decode.rs) and the cuBLASLt Q/K/V prefill arm check their ceil16(M) rows against.

Source

pub fn attn_output(&self) -> DevicePtr

Source

pub fn gate_logits(&self) -> DevicePtr

Source

pub fn gate_logits_f32(&self) -> DevicePtr

Source

pub fn moe_router_in_f32(&self) -> DevicePtr

Source

pub fn moe_output(&self) -> DevicePtr

Source

pub fn logits(&self) -> DevicePtr

Source

pub fn ssm_qkvz(&self) -> DevicePtr

Source

pub fn ssm_qkvz_bytes(&self) -> usize

2026-09-25: Allocated byte size of ssm_qkvz, the QKVZ projection’s destination on an interleaved model, checked by the cuBLASLt arm against its ceil16(M) rows.

Source

pub fn ssm_ba(&self) -> DevicePtr

Source

pub fn ssm_deinterleaved(&self) -> DevicePtr

2026-09-25: Sequential [Q|K|V|Z] rows after deinterleaving.

Source

pub fn ssm_deinterleaved_bytes(&self) -> usize

2026-09-25: Allocated byte size of ssm_deinterleaved, the QKVZ projection’s destination on a sequential model; same padded-M check.

Source

pub fn ssm_gates(&self) -> DevicePtr

2026-09-25: GDN gates in FP32: per token, linear_num_value_heads gate values, then as many beta values.

Source

pub fn ssm_conv_out_f32(&self) -> DevicePtr

2026-09-25: FP32 conv1d output of the SSM layers.

Source

pub fn scratch(&self) -> DevicePtr

2026-09-25: Scratch for MoE routing and the metadata uploads (layouts in sizes.rs).

Source

pub fn ssd_scratch(&self) -> DevicePtr

2026-09-25: Mamba-2 SSD chunked-scan scratch (dt | dA_cumsum | CB); NULL without Mamba-2 layers.

Source

pub fn token_ids(&self) -> DevicePtr

2026-09-25: Token ids [M] u32 of the pass, read by the DeepSeek-V4 hash-routed MoE layers. The caller uploads them before the layer loop, and under CUDA-graph decode before each replay.

Source

pub fn scratch_bytes(&self) -> usize

2026-09-25: Allocated byte size of scratch, the bound for metadata staging.

Source

pub fn expert_gate_out(&self) -> DevicePtr

Source

pub fn expert_up_out(&self) -> DevicePtr

Source

pub fn expert_gate_out_bytes(&self) -> usize

2026-09-25: Allocated byte size of expert_gate_out, equal to that of expert_up_out (debug-asserted).

Source

pub fn moe_output_bytes(&self) -> usize

Source

pub fn expert_down_out(&self) -> DevicePtr

Source

pub fn expert_down_out_bytes(&self) -> usize

Source

pub fn gate_logits_bytes(&self) -> usize

Source

pub fn logits_bytes(&self) -> usize

Source

pub fn attn_output_bytes(&self) -> usize

Source

pub fn gdn_fla_scratch(&self) -> DevicePtr

2026-09-25: GDN FLA prefill scratch (W | U | S | uc | gc, carved by the caller); DevicePtr::NULL unless both linear-attention head dims are 128.

Source

pub fn ffn_act_q8(&self) -> DevicePtr

2026-09-25: Shared dense-FFN q8_1 activation scratch (Q4_K MMQ); NULL for MoE.

Source

pub fn ffn_act_a(&self) -> DevicePtr

2026-09-25: Shared dense-FFN int8 / NVFP4 / FP8 activation scratch; NULL for MoE.

Source

pub fn ffn_act_scale(&self) -> DevicePtr

2026-09-25: The scales paired with ffn_act_a; NULL for MoE.

Source

pub fn ffn_gate_up_fused(&self) -> DevicePtr

2026-09-25: [ceil16(GATEUP_FUSED_MAX_M), 2 * intermediate] BF16 output of the fused dense-FFN gate+up decode GEMM: gate at column 0, up at column intermediate. NULL for MoE.

Source

pub fn ffn_gate_up_fused_bytes(&self) -> usize

2026-09-25: Allocated byte size of ffn_gate_up_fused; the fused arm selects itself only when its [ceil16(m), 2 * intermediate] output fits.

Source

pub fn ffn_act_a_bytes(&self) -> usize

Source

pub fn ffn_act_scale_bytes(&self) -> usize

Source

pub fn ffn_act_scale_kmajor(&self) -> DevicePtr

2026-09-25: [K/128, ceil16(M)] transpose of the dense-FFN FP8 activation scales for the cuBLASLt block-scaled GEMM; NULL for MoE.

Source

pub fn ffn_act_scale_kmajor_bytes(&self) -> usize

Source

pub fn fp8_act(&self) -> DevicePtr

2026-09-25: FP8 activation scratch for the prefill projections.

Source

pub fn fp8_act_bytes(&self) -> usize

Source

pub fn fp8_act_scale(&self) -> DevicePtr

2026-09-25: One FP32 scale per 128 elements of fp8_act.

Source

pub fn fp8_act_scale_bytes(&self) -> usize

Source

pub fn fp8_act_scale_kmajor(&self) -> DevicePtr

2026-09-25: [K/128, ceil16(M)] transpose of fp8_act_scale for the cuBLASLt block-scaled projections.

Source

pub fn fp8_act_scale_kmajor_bytes(&self) -> usize

Source

pub fn q2_dequant_scratch(&self) -> DevicePtr

2026-09-25: BF16 dequant scratch for keep-packed Q2_0 prefill, reused by every projection; NULL unless METRALE_GGUF_NATIVE_Q2=1.

Source

pub fn q2_dequant_scratch_bytes(&self) -> usize

Source

pub fn q2_act_q8(&self) -> DevicePtr

2026-09-25: q8_1 activation scratch for keep-packed Q2_0 MMQ prefill; NULL unless METRALE_GGUF_NATIVE_Q2_MMQ=1.

Source

pub fn q2_act_q8_bytes(&self) -> usize

Source

pub fn splitk_workspace(&self) -> DevicePtr

Source

pub fn o_latent(&self) -> DevicePtr

2026-09-25: Grouped O-projection latent [M, o_groups * o_lora_rank] BF16.

Source

pub fn norm_unit_w(&self) -> DevicePtr

2026-09-25: All-zero BF16 weight: rms_norm with it is a plain normalize.

Source

pub fn hc_streams(&self) -> DevicePtr

2026-09-25: Hyper-connection residual streams [M, hc_mult, hidden] FP32.

Source

pub fn hc_lowrank_scratch(&self) -> DevicePtr

2026-09-25: Low-rank hyper-connection scratch; its two layouts are described in sizes.rs.

Source

pub fn qsa_select_scratch(&self) -> DevicePtr

2026-09-25: QSA prefill-selection scratch shared by the indexer layers; layers/qsa_select.rs carves it as sizes.rs sizes it.

Source

pub fn hc_post(&self) -> DevicePtr

2026-09-25: Hyper-connection post weights [M, hc_mult] F32.

Source

pub fn hc_comb(&self) -> DevicePtr

2026-09-25: Hyper-connection comb matrix [M, hc_mult, hc_mult] F32.

Source

pub fn max_batch_tokens(&self) -> usize

Source

pub fn decode_meta(&self) -> DecodeMetaLayout

2026-09-25: The batched-decode metadata layout.

Source

pub fn sizes(&self) -> &BufferSizes

Source

pub fn lora_xa(&self) -> DevicePtr

2026-09-25: LoRA shrink scratch xa = x @ Aᵀ, [M, adapter_max_rank] BF16; DevicePtr::NULL without an adapter.

Source

pub fn lora_xa_bytes(&self) -> usize

Source

pub fn lora_delta(&self) -> DevicePtr

2026-09-25: LoRA expand scratch delta = xa @ Bᵀ BF16; DevicePtr::NULL without an adapter.

Source

pub fn lora_delta_bytes(&self) -> usize

Source

pub fn lora_hact(&self) -> DevicePtr

2026-09-25: LoRA hidden-activation scratch [M, intermediate_size] BF16; DevicePtr::NULL without an adapter.

Source

pub fn lora_hact_bytes(&self) -> usize

Source

pub fn lora_seq_slot(&self) -> DevicePtr

2026-09-25: LoRA adapter slot per prefill token, [M] i32; DevicePtr::NULL without an adapter.

Source

pub fn zero_prefill_essentials( &self, gpu: &dyn GpuBackend, stream: u64, ) -> Result<()>

2026-09-25: Zero hidden_states, residual, gate_logits, the three expert outputs and moe_output: seven memsets, where zero_all issues eighteen. The prefill paths call this on a sequence’s first chunk when they do not call zero_all.

Source

pub fn zero_all_rows( &self, gpu: &dyn GpuBackend, stream: u64, tokens: usize, ) -> Result<()>

2026-09-25: zero_all limited to the first tokens rows of each token-major buffer: for a buffer whose size is a multiple of max_batch_tokens, size / max_batch_tokens * tokens bytes; any other buffer, and every buffer when tokens >= max_batch_tokens, is zeroed whole. splitk_workspace, logits and scratch are zeroed whole. The caller must read only rows 0..tokens. Measured 2026-08-28 on GLM-5.3-Flash (nsys, max_batch_tokens = 4096): zero_all took 8.01 ms of an 85 ms decode step.

Source

pub fn zero_all(&self, gpu: &dyn GpuBackend, stream: u64) -> Result<()>

2026-09-25: Zero, in full, the eighteen buffers zero_all_rows covers. The others (gate_logits_f32, moe_router_in_f32, o_latent, norm_unit_w, the hyper-connection, QSA, FLA and SSD scratch, token_ids, ffn_*, fp8_*, q2_*, lora_* and the row-wise slab) keep their contents.

Source§

impl BufferArena

Source

pub fn debug_buffer_checksum( &self, gpu: &dyn GpuBackend, stream: u64, tag: &str, )

2026-09-25: Synchronize stream, then log at warn level the sum, sum of squares and sum of absolute values of each listed buffer read as f32 lanes over its whole allocation (non-finite lanes skipped), tagged with tag. A failed synchronize or copy is ignored; a failed copy skips that buffer. The model engine calls it at the first decode step when ssm_save_dump is set.

Source§

impl BufferArena

Source

pub fn moe_fp8_scratch( &self, c: &ModelConfig, rows: usize, ) -> Result<MoeFp8Scratch>

2026-09-25: Fixed offsets for a given shape, without allocating or mutating ownership.

§Errors

When rows exceeds the arena’s batch, the model has no experts, the shape needs more than the slab holds, or the slab was released.

Source§

impl BufferArena

Source

pub fn ssm_rowwise_w_bf16_bytes(&self) -> usize

2026-09-25: Allocated byte size of the slab; 0 unless METRALE_FP8_ROWWISE=1 when the arena was sized.

Source

pub fn take_ssm_rowwise_w_bf16(&self, bytes: usize) -> Result<DevicePtr>

2026-09-25: Carve the next bytes of the slab. Slices are never returned: a GDN layer carves its in_proj_qkvz and out_proj copies on its first prefill and keeps them for the arena’s life. The slab holds exactly num_ssm_layers such pairs (sizes_rowwise.rs), so exhaustion is a sizing bug and is returned as an error, not served by a new allocation. The cursor is not rolled back after that error.

Relaxed ordering: the scheduler runs one forward at a time, the same assumption cublaslt::Ctx states for its Send/Sync.

Source§

impl BufferArena

Source

pub fn new( config: &ModelConfig, max_batch_tokens: usize, max_seq_len: usize, kv_block_size: usize, max_batch_size: usize, gpu: &dyn GpuBackend, ) -> Result<Self>

2026-09-25: Size the buffers with BufferSizes::from_config and allocate them.

Source

pub fn from_sizes( config: &ModelConfig, sizes: BufferSizes, max_batch_tokens: usize, max_batch_size: usize, gpu: &dyn GpuBackend, ) -> Result<Self>

2026-09-25: BufferArena::new with the sizes passed in.

BufferSizes::from_config reads the environment for the env-gated entries (q2_*, ssm_rowwise_w_bf16), so a test that needs one of them sized builds the sizes itself and calls this instead of setting a process-global variable. On an allocation error the buffers already allocated are not freed.

Trait Implementations§

Source§

impl ModelResource<dyn GpuBackend> for BufferArena

2026-09-25: The destructure in release names every field, with no .., so a field added to BufferArena does not compile until it is handled here. Free the new buffer rather than adding a wildcard: a missed free is a leak that shows only as the next model failing to fit.

Source§

fn label(&self) -> &'static str

2026-09-25: Human name, used to attribute a failure in Teardown::release_all’s error.
Source§

fn release(&mut self, gpu: &dyn GpuBackend) -> Result<()>

2026-09-25: Release everything this owns. Must be idempotent.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more