metrale_gpu_runtime/buffers/
sizes_rowwise.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: Size of the row-wise FP8 GDN prefill BF16-weight slab: 0 unless `METRALE_FP8_ROWWISE=1`.
4//!
5//! The row-wise GDN prefill arms multiply BF16 copies of their per-row FP8
6//! weights. Sizing the copies here makes them one arena allocation that the
7//! preflight reserve (`BufferSizes::total_bytes`) counts; the arms carve their
8//! slices from it (`rowwise_slab.rs`).
9//!
10//! Owner: gpu-runtime.
11//! Invariants:
12//! - [`ssm_rowwise_w_bf16_bytes`] reads the lever with the same predicate as
13//!   the loader's `rowwise_fp8_enabled` (`== "1"`).
14
15use metrale_config::ModelConfig;
16
17/// 2026-09-25: BF16 bytes of one GDN layer's row-wise copies: `in_proj_qkvz`
18/// `[ssm_qkvz_size, hidden]` and `out_proj` `[hidden, value_dim]`, the two
19/// weights `set_fp8_rowwise_prefill_weights` installs, with
20/// `value_dim = linear_num_value_heads * linear_value_head_dim`. At the
21/// Qwen3.8-27B shapes of `buffers/tests.rs` (hidden 5120, 16x128 key heads,
22/// 48x128 value heads) that is `167772160 + 62914560` B.
23pub fn ssm_rowwise_w_bf16_layer_bytes(config: &ModelConfig) -> usize {
24    let bf16 = 2;
25    let value_dim = config.linear_num_value_heads * config.linear_value_head_dim;
26    let qkvz = config.ssm_qkvz_size() * config.hidden_size * bf16;
27    let out_proj = config.hidden_size * value_dim * bf16;
28    qkvz + out_proj
29}
30
31/// 2026-09-25: Slab bytes: the per-layer pair times `num_ssm_layers`, or 0
32/// unless `METRALE_FP8_ROWWISE=1`. The predicate is the one in the loader's
33/// `rowwise_fp8_enabled` (`weight_loader/qwen35_dense/rowwise_fp8.rs`): the
34/// loader installs the row-wise weights on it and the arms then need this
35/// slab, so the two must agree.
36pub fn ssm_rowwise_w_bf16_bytes(config: &ModelConfig) -> usize {
37    ssm_rowwise_w_bf16_bytes_for(
38        config,
39        std::env::var("METRALE_FP8_ROWWISE").as_deref() == Ok("1"),
40    )
41}
42
43/// 2026-09-25: [`ssm_rowwise_w_bf16_bytes`] with the lever passed in, for tests
44/// that must not set the process environment.
45pub fn ssm_rowwise_w_bf16_bytes_for(config: &ModelConfig, rowwise_enabled: bool) -> usize {
46    if !rowwise_enabled {
47        return 0;
48    }
49    config.num_ssm_layers() * ssm_rowwise_w_bf16_layer_bytes(config)
50}