Skip to main content

QTensor

Enum QTensor 

Source
pub enum QTensor {
    F32 {
        data: Vec<f32>,
        rows: usize,
        cols: usize,
    },
    Mapped {
        model: Arc<CmfModel>,
        idx: usize,
        dtype: TensorDtype,
        rows: usize,
        cols: usize,
        row_scale: Vec<f32>,
        col_field: Vec<f32>,
        vbit_offsets: Vec<usize>,
        repack: Vec<u8>,
    },
}

Variants§

§

F32

Fields

§data: Vec<f32>
§rows: usize
§cols: usize
§

Mapped

Fields

§model: Arc<CmfModel>
§idx: usize

Index into the model’s tensor directory.

§rows: usize
§cols: usize
§row_scale: Vec<f32>

Per-row scales, dequantized to f32 up front (tiny).

§col_field: Vec<f32>

q8_2f column field (θ), dequantized up front; empty for q8_row.

§vbit_offsets: Vec<usize>

Vbit only: byte offset of each row’s packed data within the tensor blob ([rows + 1], computed once at load — the per- matvec prefix scan over row bit-widths was O(rows) each call).

§repack: Vec<u8>

q8-family decode repack (load-time, optional): rows in groups of 4, interleaved in 16-byte units — one 64-byte line per iteration feeds all 4 sdot lanes, ONE sequential weight stream per worker instead of four (this is where llama.cpp’s repacked Q8 kernels get their bandwidth). Empty = off (CMF_REPACK=0, non-SDOT arch, or an ineligible shape). Trades an anonymous copy of the quants for mmap pages that go cold.

Implementations§

Source§

impl QTensor

Source

pub fn from_f32(data: Vec<f32>, rows: usize, cols: usize) -> Self

Source

pub fn from_model(model: &Arc<CmfModel>, name: &str) -> Result<Self, String>

Wrap a directory tensor without dequantizing the payload. Falls back to dequantized f32 for dtypes without a fused kernel.

Examples found in repository?
examples/dsv41_engram_component.rs (line 171)
154fn main() -> Result<(), Box<dyn Error>> {
155    let mut args = std::env::args_os().skip(1);
156    let dir = PathBuf::from(args.next().ok_or("missing raw fixture directory")?);
157    let layer = dir
158        .file_name()
159        .and_then(|s| s.to_str())
160        .and_then(|s| s.strip_prefix("raw-layer-"))
161        .ok_or("fixture directory must be named raw-layer-N")?;
162    let prefix = format!("model.layers.{layer}.engram");
163    let cmf = dir.join("engram-component.cmf");
164    write_fixture(&dir, &cmf)?;
165    let model = Arc::new(CmfModel::open(&cmf)?);
166    let embed = RawFp8Rows::from_model(
167        &model,
168        &format!("{prefix}.embed.weight"),
169        &format!("{prefix}.embed.scale"),
170    )?;
171    let wkv = QTensor::from_model(&model, &format!("{prefix}.wkv.weight"))?;
172    let q_weight = f32_tensor(&model, &format!("{prefix}.q_weight"))?;
173    let k_weight = f32_tensor(&model, &format!("{prefix}.k_weight"))?;
174    let engram = Dsv41Engram {
175        embed,
176        wkv,
177        q_weight,
178        k_weight,
179    };
180    let cfg = cfg();
181    let meta: Value = serde_json::from_slice(&fs::read(dir.join("manifest.json"))?)?;
182    let mut max_abs = 0.0f32;
183    let mut sum_abs = 0.0f64;
184    let mut count = 0usize;
185    let mut cases = 0usize;
186    for case in 0..3 {
187        let prefix = format!("case{case}");
188        let input_shape = meta[&format!("{prefix}.input")]["shape"]
189            .as_array()
190            .unwrap();
191        let seq = input_shape[1].as_u64().unwrap() as usize;
192        let input = read_bf16(&dir.join(format!("{prefix}_input.bin")))?;
193        let expected = read_bf16(&dir.join(format!("{prefix}_output.bin")))?;
194        let index_bytes = fs::read(dir.join(format!("{prefix}_indices.bin")))?;
195        let mut indices = Vec::with_capacity(index_bytes.len() / 8);
196        for b in index_bytes.chunks_exact(8) {
197            indices.push(u64::from_le_bytes(b.try_into().unwrap()) as usize);
198        }
199        let token_mask: Vec<bool> = if case == 1 {
200            vec![
201                true, true, true, true, true, false, false, false, true, true, true, true, true,
202                true, true, true, true, true, true, true,
203            ]
204        } else {
205            vec![true; seq]
206        };
207        for token in 0..seq {
208            let mut h = input[token * 4 * 5120..(token + 1) * 4 * 5120].to_vec();
209            let hashes = &indices[token * 24..(token + 1) * 24];
210            dsv41_apply_engram_for_test(&engram, &mut h, hashes, &cfg, token_mask[token]);
211            for (&got, &want) in h
212                .iter()
213                .zip(&expected[token * 4 * 5120..(token + 1) * 4 * 5120])
214            {
215                let d = (got - want).abs();
216                max_abs = max_abs.max(d);
217                sum_abs += d as f64;
218                count += 1;
219            }
220        }
221        cases += 1;
222        println!("case={case} seq={seq} cumulative_max_abs={max_abs:.8e}",);
223    }
224    println!(
225        "summary cases={cases} values={count} max_abs={max_abs:.8e} mean_abs={:.8e}",
226        sum_abs / count.max(1) as f64
227    );
228    Ok(())
229}
More examples
Hide additional examples
examples/matvec_bw.rs (line 55)
21fn main() {
22    let mut args = std::env::args().skip(1);
23    let path = args
24        .next()
25        .expect("usage: matvec_bw <model.cmf> [sweep|one <tensor>]");
26    let mode = args.next().unwrap_or_else(|| "sweep".to_string());
27    let model = Arc::new(cortiq_core::CmfModel::open(&path).expect("open model"));
28
29    // Real LM activations carry a few heavy channels (>8·rms); measured
30    // mean on this model is ~3.7. NOUT models that distribution.
31    let nout: usize = std::env::var("NOUT")
32        .ok()
33        .and_then(|v| v.parse().ok())
34        .unwrap_or(4);
35    let mk_x = |cols: usize| -> Vec<f32> {
36        let mut x: Vec<f32> = (0..cols).map(|i| ((i % 17) as f32 - 8.0) / 8.0).collect();
37        for k in 0..nout {
38            x[k * 37 % cols] = 40.0;
39        }
40        x
41    };
42
43    if mode == "one" {
44        let name = args
45            .next()
46            .unwrap_or_else(|| "model.embed_tokens.weight".to_string());
47        let entry = model.tensor(&name).expect("tensor not found");
48        let (rows, cols) = (entry.shape[0], entry.shape[1]);
49        let nbytes = entry.nbytes as f64;
50        println!(
51            "tensor {name}: {rows}x{cols} {:?} = {:.1} MB, NOUT={nout}",
52            entry.dtype,
53            nbytes / 1e6
54        );
55        let t = QTensor::from_model(&model, &name).expect("wrap");
56        let x = mk_x(cols);
57        let mut out = vec![0f32; rows];
58        t.matvec(&x, &mut out, None);
59        for nt in [1usize, 2, 4, 6, 8, 10] {
60            let pool = if nt == 1 { None } else { Some(Pool::new(nt)) };
61            let iters = 8;
62            t.matvec(&x, &mut out, pool.as_ref());
63            let t0 = Instant::now();
64            for _ in 0..iters {
65                t.matvec(&x, &mut out, pool.as_ref());
66            }
67            let el = t0.elapsed().as_secs_f64();
68            println!(
69                "threads={nt:2}  {:6.2} ms/matvec  {:6.1} GB/s (sink {:.3})",
70                el / iters as f64 * 1e3,
71                nbytes * iters as f64 / el / 1e9,
72                out[0]
73            );
74        }
75        return;
76    }
77
78    // sweep: every 2-D q8_2f tensor once = one decode's worth of weights.
79    let names: Vec<String> = model
80        .tensors
81        .iter()
82        .filter(|t| t.dtype == TensorDtype::Q8_2f && t.shape.len() == 2)
83        .map(|t| t.name.clone())
84        .collect();
85    let total_bytes: f64 = model
86        .tensors
87        .iter()
88        .filter(|t| t.dtype == TensorDtype::Q8_2f && t.shape.len() == 2)
89        .map(|t| t.nbytes as f64)
90        .sum();
91    println!(
92        "sweep: {} q8_2f tensors, {:.2} GB total (= weights streamed per decode token), NOUT={nout}",
93        names.len(),
94        total_bytes / 1e9
95    );
96
97    let tensors: Vec<(QTensor, Vec<f32>, Vec<f32>)> = names
98        .iter()
99        .map(|n| {
100            let e = model.tensor(n).unwrap();
101            let (rows, cols) = (e.shape[0], e.shape[1]);
102            (
103                QTensor::from_model(&model, n).expect("wrap"),
104                mk_x(cols),
105                vec![0f32; rows],
106            )
107        })
108        .collect();
109    let mut tensors = tensors;
110
111    // Whole-model residency pass BEFORE any timing: the first touch of a
112    // 4.2 GB mmap faults ~260k pages, which would otherwise be charged to
113    // whichever thread count happens to run first. REVERSE=1 flips the
114    // order as a check that no first-touch cost is left in the table.
115    for _ in 0..2 {
116        for (t, x, out) in tensors.iter_mut() {
117            t.matvec(x, out, None);
118        }
119    }
120    let mut counts = vec![1usize, 2, 4, 6, 8, 10];
121    if std::env::var("REVERSE").is_ok() {
122        counts.reverse();
123    }
124    for nt in counts {
125        let pool = if nt == 1 { None } else { Some(Pool::new(nt)) };
126        // one warm pass, then two measured
127        for (t, x, out) in tensors.iter_mut() {
128            t.matvec(x, out, pool.as_ref());
129        }
130        let iters = 2;
131        let t0 = Instant::now();
132        for _ in 0..iters {
133            for (t, x, out) in tensors.iter_mut() {
134                t.matvec(x, out, pool.as_ref());
135            }
136        }
137        let el = t0.elapsed().as_secs_f64();
138        let per_tok = el / iters as f64;
139        println!(
140            "threads={nt:2}  {:7.1} ms/sweep  {:6.1} GB/s  -> weight-path-only ceiling {:5.1} tok/s",
141            per_tok * 1e3,
142            total_bytes * iters as f64 / el / 1e9,
143            1.0 / per_tok
144        );
145    }
146}
examples/dsv41_engram_proof.rs (line 353)
329fn verify_component_layer(
330    root: &Path,
331    projected_root: &Path,
332    layer: usize,
333    reference_hashes: &[Vec<Vec<Vec<usize>>>],
334) -> Result<(), Box<dyn Error>> {
335    let dir = root.join(format!("raw-layer-{layer}"));
336    let layer_meta: Value =
337        serde_json::from_slice(&fs::read(root.join(format!("layer-{layer}.json")))?)?;
338    let original_rows: Vec<usize> = serde_json::from_value(layer_meta["original_row_ids"].clone())?;
339    let row_to_compact: HashMap<usize, usize> = original_rows
340        .iter()
341        .copied()
342        .enumerate()
343        .map(|(compact, original)| (original, compact))
344        .collect();
345    let prefix = format!("model.layers.{layer}.engram");
346    let cmf = dir.join("engram-component.cmf");
347    let model = Arc::new(CmfModel::open(&cmf)?);
348    let embed = RawFp8Rows::from_model(
349        &model,
350        &format!("{prefix}.embed.weight"),
351        &format!("{prefix}.embed.scale"),
352    )?;
353    let wkv = QTensor::from_model(&model, &format!("{prefix}.wkv.weight"))?;
354    let q_weight = f32_tensor(&model, &format!("{prefix}.q_weight"))?;
355    let k_weight = f32_tensor(&model, &format!("{prefix}.k_weight"))?;
356    let engram = Dsv41Engram {
357        embed,
358        wkv,
359        q_weight,
360        k_weight,
361    };
362    let cases = layer_meta["cases"]
363        .as_array()
364        .ok_or("layer cases missing")?;
365    for (case_no, case) in cases.iter().enumerate() {
366        let original_hashes: Vec<Vec<usize>> =
367            serde_json::from_value(case["original_hash_ids"].clone())?;
368        if original_hashes.len() != reference_hashes[case_no].len() {
369            return Err(format!("layer {layer} case {case_no} sequence length mismatch").into());
370        }
371        let mut expected_compact = Vec::with_capacity(original_hashes.len() * HASH_COLS);
372        for (pos, rows) in original_hashes.iter().enumerate() {
373            if rows.len() != HASH_COLS || reference_hashes[case_no][pos][0].len() != HASH_COLS {
374                return Err(format!("layer {layer} case {case_no} hash width mismatch").into());
375            }
376            let layer_index = if layer == 1 { 0 } else { 1 };
377            if rows != &reference_hashes[case_no][pos][layer_index] {
378                return Err(format!(
379                    "layer {layer} case {case_no} original indices differ from full hash oracle at position {pos}"
380                )
381                .into());
382            }
383            for &row in rows {
384                expected_compact.push(
385                    *row_to_compact
386                        .get(&row)
387                        .ok_or_else(|| format!("layer {layer} missing compact row for {row}"))?,
388                );
389            }
390        }
391        let got_compact = read_i64(&dir.join(format!("case{case_no}_indices.bin")))?;
392        if got_compact != expected_compact {
393            let first = got_compact
394                .iter()
395                .zip(&expected_compact)
396                .enumerate()
397                .find(|(_, (a, b))| a != b);
398            return Err(format!(
399                "layer {layer} case {case_no} compact indices mismatch: {first:?}"
400            )
401            .into());
402        }
403
404        let seq = original_hashes.len();
405        let mut gathered = vec![0.0f32; seq * HASH_COLS * 256];
406        for token in 0..seq {
407            for col in 0..HASH_COLS {
408                engram.embed.row_into(
409                    got_compact[token * HASH_COLS + col],
410                    &mut gathered
411                        [(token * HASH_COLS + col) * 256..(token * HASH_COLS + col + 1) * 256],
412                );
413            }
414        }
415        gathered.iter_mut().for_each(|v| *v = bf16_roundtrip(*v));
416        compare_bf16(
417            &format!("layer={layer} case={case_no} gathered"),
418            &gathered,
419            &read_bf16(&dir.join(format!("case{case_no}_gathered.bin")))?,
420        )?;
421
422        let mut projected = Vec::with_capacity(seq * (DIM * (HC_MULT + 1)));
423        for token in 0..seq {
424            let input = &gathered[token * HASH_COLS * 256..(token + 1) * HASH_COLS * 256];
425            let mut row = vec![0.0f32; DIM * (HC_MULT + 1)];
426            engram.wkv.matvec(input, &mut row, None);
427            row.iter_mut().for_each(|v| *v = bf16_roundtrip(*v));
428            projected.extend_from_slice(&row);
429        }
430        compare_bf16(
431            &format!("layer={layer} case={case_no} projected"),
432            &projected,
433            &read_bf16(&projected_root.join(format!("layer-{layer}/case{case_no}_projected.bin")))?,
434        )?;
435
436        let input = read_bf16(&dir.join(format!("case{case_no}_input.bin")))?;
437        let expected_output = read_bf16(&dir.join(format!("case{case_no}_output.bin")))?;
438        let mask: Option<Vec<bool>> = if case["token_mask"].is_null() {
439            None
440        } else {
441            Some(serde_json::from_value(case["token_mask"].clone())?)
442        };
443        let mut output = Vec::with_capacity(input.len());
444        for token in 0..seq {
445            let mut h = input[token * HC_MULT * DIM..(token + 1) * HC_MULT * DIM].to_vec();
446            dsv41_apply_engram_for_test(
447                &engram,
448                &mut h,
449                &got_compact[token * HASH_COLS..(token + 1) * HASH_COLS],
450                &cfg(),
451                mask.as_ref().map(|m| m[token]).unwrap_or(true),
452            );
453            output.extend_from_slice(&h);
454        }
455        compare_bf16(
456            &format!("layer={layer} case={case_no} output"),
457            &output,
458            &expected_output,
459        )?;
460        println!(
461            "component layer={} case={} name={} compact_indices=true gathered=true projected=true output=true",
462            layer,
463            case_no,
464            case["name"].as_str().unwrap_or("?")
465        );
466    }
467    Ok(())
468}
Source

pub fn model_dtype(&self) -> Option<TensorDtype>

The layout this tensor is stored in, when it is mapped from a model. The frames branch on it — a q2tp gate against a q4tp down is a real combination in the 2-bit profile and needs a different kernel.

Source

pub fn model_idx(&self) -> Option<usize>

The tensor’s index in the model directory, when it is mapped from one. The GPU frames bind by index rather than by name — a name lookup per layer per token is not free, and the index is what the device cache is keyed on anyway.

Source

pub fn model_arc(&self) -> Option<Arc<CmfModel>>

The model this tensor is mapped from, when it is mapped at all. The GPU frames need the container to reach the bytes; a QTensor already holds it, and threading a second handle down every call site to say the same thing invites the two to disagree.

Source

pub fn rows(&self) -> usize

Source

pub fn mapped_q4tp(&self) -> Option<(&Arc<CmfModel>, usize)>

Same slot as mapped_q4t for a q4tp tensor — the fused DiT FFN picks its kernels by which of the two answers.

Source

pub fn mapped_device_gemm(&self) -> Option<(&Arc<CmfModel>, usize)>

(model, tensor idx) for a mapped weight in ANY codec the fused device paths can run — four-bit tiled or either int8 layout.

The fused DiT chains asked for mapped_q4tp by name, so an eight-bit container never reached them and rendered through per-op GEMMs even after those kernels learned its codec. The gate is what the codec has a device GEMM for, not which codec it is.

Source

pub fn mapped_q2tp(&self) -> Option<(&Arc<CmfModel>, usize)>

(model, tensor idx) for a q2tp mapped weight — the 2-bit twin of mapped_q4tp, used by the mixed MoE profile.

Source

pub fn cols(&self) -> usize

Source

pub fn mapped_q1(&self) -> Option<(&Arc<CmfModel>, usize)>

(model, tensor idx) for a q1 mapped weight — the wgpu token graph keys its resident VRAM cache by idx. None for any other dtype/kind.

Source

pub fn graph_weight(&self) -> Option<(&Arc<CmfModel>, usize, u8, &[f32])>

(model, idx, kind, row_scale) for a graph-capable mapped weight. kind: 0=q8_row (per-row scales), 1=q1, 2=q4_block, 3=q1t (tile-embedded, no rs), 5=q4_tiled, 6=q4tp, 7=q8_2f (both scale planes live inside the tensor). None only for vbit.

The old comment here claimed q4_block was unhandled while the arm right below mapped it, and it named q8_2f as unhandled after that stopped being true — a stale comment on this function is how a model silently loses the graph, so it is worth keeping honest.

Source

pub fn as_f32(&self) -> Option<&[f32]>

Dense f32 view — only for owned tensors. Masked/sparse execution paths require it; quantized weights don’t support masks yet.

Source

pub fn row_f32(&self, r: usize, dst: &mut [f32])

Dequantize one row into dst (embedding lookup).

Source

pub fn sparse_col_ok(&self) -> bool

Can this tensor’s columns be read cheaply (for sparse down_proj)? True for F32/Q8Row/Q8_2f (per-row scale, direct strided access); false for group-packed q4/vbit (column access would unpack whole groups — sparse execution falls back to f32 for those).

Source

pub fn add_col_scaled(&self, c: usize, w: f32, out: &mut [f32])

down_proj [hidden, inter]: accumulate w · col(c) into out [hidden] — reads ONLY column c (one neuron) from the mmap, no full-matrix dequant. out[k] += w · down[k, c].

Source

pub fn prefetch_row(&self, r: usize)

Touch the head of row r so the DRAM latency of the next neuron’s weights overlaps the current one’s arithmetic.

Scattered rows are what per-token sparsity reads, and a 2 KB stride is past what the hardware prefetcher follows: without this every row starts with a cold miss that nothing hides. One touch per 512 bytes is enough — the rest of the row is a sequential run the prefetcher does pick up.

Source

pub fn add_row_scaled( &self, r: usize, w: f32, out: &mut [f32], scratch: &mut [f32], )

out += w · row(r) — the transposed twin of add_col_scaled.

A neuron’s down weights are a COLUMN of [hidden, inter], and a column is strided: reading one costs a cache line per element, so per-neuron dynamic sparsity saves arithmetic and no bytes. Stored transposed (down_proj.t.weight, [inter, hidden]) the same weights are a contiguous ROW, and this accumulate reads exactly the neurons the token asked for.

Source

pub fn row_dot(&self, r: usize, x: &[f32], scratch: &mut [f32]) -> f32

Dot of row r with x (gate/up active-neuron path). Reads only row r from the mmap — no full dequant. q4/vbit dequant the row into scratch first (rare for active-FFN weights).

Source

pub fn matvec(&self, x: &[f32], out: &mut [f32], pool: Option<&Pool>)

out = W · x (row-major). F32 delegates to the historical bit-exact path; Mapped runs the fused int8 kernel.

Examples found in repository?
examples/matvec_bw.rs (line 58)
21fn main() {
22    let mut args = std::env::args().skip(1);
23    let path = args
24        .next()
25        .expect("usage: matvec_bw <model.cmf> [sweep|one <tensor>]");
26    let mode = args.next().unwrap_or_else(|| "sweep".to_string());
27    let model = Arc::new(cortiq_core::CmfModel::open(&path).expect("open model"));
28
29    // Real LM activations carry a few heavy channels (>8·rms); measured
30    // mean on this model is ~3.7. NOUT models that distribution.
31    let nout: usize = std::env::var("NOUT")
32        .ok()
33        .and_then(|v| v.parse().ok())
34        .unwrap_or(4);
35    let mk_x = |cols: usize| -> Vec<f32> {
36        let mut x: Vec<f32> = (0..cols).map(|i| ((i % 17) as f32 - 8.0) / 8.0).collect();
37        for k in 0..nout {
38            x[k * 37 % cols] = 40.0;
39        }
40        x
41    };
42
43    if mode == "one" {
44        let name = args
45            .next()
46            .unwrap_or_else(|| "model.embed_tokens.weight".to_string());
47        let entry = model.tensor(&name).expect("tensor not found");
48        let (rows, cols) = (entry.shape[0], entry.shape[1]);
49        let nbytes = entry.nbytes as f64;
50        println!(
51            "tensor {name}: {rows}x{cols} {:?} = {:.1} MB, NOUT={nout}",
52            entry.dtype,
53            nbytes / 1e6
54        );
55        let t = QTensor::from_model(&model, &name).expect("wrap");
56        let x = mk_x(cols);
57        let mut out = vec![0f32; rows];
58        t.matvec(&x, &mut out, None);
59        for nt in [1usize, 2, 4, 6, 8, 10] {
60            let pool = if nt == 1 { None } else { Some(Pool::new(nt)) };
61            let iters = 8;
62            t.matvec(&x, &mut out, pool.as_ref());
63            let t0 = Instant::now();
64            for _ in 0..iters {
65                t.matvec(&x, &mut out, pool.as_ref());
66            }
67            let el = t0.elapsed().as_secs_f64();
68            println!(
69                "threads={nt:2}  {:6.2} ms/matvec  {:6.1} GB/s (sink {:.3})",
70                el / iters as f64 * 1e3,
71                nbytes * iters as f64 / el / 1e9,
72                out[0]
73            );
74        }
75        return;
76    }
77
78    // sweep: every 2-D q8_2f tensor once = one decode's worth of weights.
79    let names: Vec<String> = model
80        .tensors
81        .iter()
82        .filter(|t| t.dtype == TensorDtype::Q8_2f && t.shape.len() == 2)
83        .map(|t| t.name.clone())
84        .collect();
85    let total_bytes: f64 = model
86        .tensors
87        .iter()
88        .filter(|t| t.dtype == TensorDtype::Q8_2f && t.shape.len() == 2)
89        .map(|t| t.nbytes as f64)
90        .sum();
91    println!(
92        "sweep: {} q8_2f tensors, {:.2} GB total (= weights streamed per decode token), NOUT={nout}",
93        names.len(),
94        total_bytes / 1e9
95    );
96
97    let tensors: Vec<(QTensor, Vec<f32>, Vec<f32>)> = names
98        .iter()
99        .map(|n| {
100            let e = model.tensor(n).unwrap();
101            let (rows, cols) = (e.shape[0], e.shape[1]);
102            (
103                QTensor::from_model(&model, n).expect("wrap"),
104                mk_x(cols),
105                vec![0f32; rows],
106            )
107        })
108        .collect();
109    let mut tensors = tensors;
110
111    // Whole-model residency pass BEFORE any timing: the first touch of a
112    // 4.2 GB mmap faults ~260k pages, which would otherwise be charged to
113    // whichever thread count happens to run first. REVERSE=1 flips the
114    // order as a check that no first-touch cost is left in the table.
115    for _ in 0..2 {
116        for (t, x, out) in tensors.iter_mut() {
117            t.matvec(x, out, None);
118        }
119    }
120    let mut counts = vec![1usize, 2, 4, 6, 8, 10];
121    if std::env::var("REVERSE").is_ok() {
122        counts.reverse();
123    }
124    for nt in counts {
125        let pool = if nt == 1 { None } else { Some(Pool::new(nt)) };
126        // one warm pass, then two measured
127        for (t, x, out) in tensors.iter_mut() {
128            t.matvec(x, out, pool.as_ref());
129        }
130        let iters = 2;
131        let t0 = Instant::now();
132        for _ in 0..iters {
133            for (t, x, out) in tensors.iter_mut() {
134                t.matvec(x, out, pool.as_ref());
135            }
136        }
137        let el = t0.elapsed().as_secs_f64();
138        let per_tok = el / iters as f64;
139        println!(
140            "threads={nt:2}  {:7.1} ms/sweep  {:6.1} GB/s  -> weight-path-only ceiling {:5.1} tok/s",
141            per_tok * 1e3,
142            total_bytes * iters as f64 / el / 1e9,
143            1.0 / per_tok
144        );
145    }
146}
More examples
Hide additional examples
examples/dsv41_engram_proof.rs (line 426)
329fn verify_component_layer(
330    root: &Path,
331    projected_root: &Path,
332    layer: usize,
333    reference_hashes: &[Vec<Vec<Vec<usize>>>],
334) -> Result<(), Box<dyn Error>> {
335    let dir = root.join(format!("raw-layer-{layer}"));
336    let layer_meta: Value =
337        serde_json::from_slice(&fs::read(root.join(format!("layer-{layer}.json")))?)?;
338    let original_rows: Vec<usize> = serde_json::from_value(layer_meta["original_row_ids"].clone())?;
339    let row_to_compact: HashMap<usize, usize> = original_rows
340        .iter()
341        .copied()
342        .enumerate()
343        .map(|(compact, original)| (original, compact))
344        .collect();
345    let prefix = format!("model.layers.{layer}.engram");
346    let cmf = dir.join("engram-component.cmf");
347    let model = Arc::new(CmfModel::open(&cmf)?);
348    let embed = RawFp8Rows::from_model(
349        &model,
350        &format!("{prefix}.embed.weight"),
351        &format!("{prefix}.embed.scale"),
352    )?;
353    let wkv = QTensor::from_model(&model, &format!("{prefix}.wkv.weight"))?;
354    let q_weight = f32_tensor(&model, &format!("{prefix}.q_weight"))?;
355    let k_weight = f32_tensor(&model, &format!("{prefix}.k_weight"))?;
356    let engram = Dsv41Engram {
357        embed,
358        wkv,
359        q_weight,
360        k_weight,
361    };
362    let cases = layer_meta["cases"]
363        .as_array()
364        .ok_or("layer cases missing")?;
365    for (case_no, case) in cases.iter().enumerate() {
366        let original_hashes: Vec<Vec<usize>> =
367            serde_json::from_value(case["original_hash_ids"].clone())?;
368        if original_hashes.len() != reference_hashes[case_no].len() {
369            return Err(format!("layer {layer} case {case_no} sequence length mismatch").into());
370        }
371        let mut expected_compact = Vec::with_capacity(original_hashes.len() * HASH_COLS);
372        for (pos, rows) in original_hashes.iter().enumerate() {
373            if rows.len() != HASH_COLS || reference_hashes[case_no][pos][0].len() != HASH_COLS {
374                return Err(format!("layer {layer} case {case_no} hash width mismatch").into());
375            }
376            let layer_index = if layer == 1 { 0 } else { 1 };
377            if rows != &reference_hashes[case_no][pos][layer_index] {
378                return Err(format!(
379                    "layer {layer} case {case_no} original indices differ from full hash oracle at position {pos}"
380                )
381                .into());
382            }
383            for &row in rows {
384                expected_compact.push(
385                    *row_to_compact
386                        .get(&row)
387                        .ok_or_else(|| format!("layer {layer} missing compact row for {row}"))?,
388                );
389            }
390        }
391        let got_compact = read_i64(&dir.join(format!("case{case_no}_indices.bin")))?;
392        if got_compact != expected_compact {
393            let first = got_compact
394                .iter()
395                .zip(&expected_compact)
396                .enumerate()
397                .find(|(_, (a, b))| a != b);
398            return Err(format!(
399                "layer {layer} case {case_no} compact indices mismatch: {first:?}"
400            )
401            .into());
402        }
403
404        let seq = original_hashes.len();
405        let mut gathered = vec![0.0f32; seq * HASH_COLS * 256];
406        for token in 0..seq {
407            for col in 0..HASH_COLS {
408                engram.embed.row_into(
409                    got_compact[token * HASH_COLS + col],
410                    &mut gathered
411                        [(token * HASH_COLS + col) * 256..(token * HASH_COLS + col + 1) * 256],
412                );
413            }
414        }
415        gathered.iter_mut().for_each(|v| *v = bf16_roundtrip(*v));
416        compare_bf16(
417            &format!("layer={layer} case={case_no} gathered"),
418            &gathered,
419            &read_bf16(&dir.join(format!("case{case_no}_gathered.bin")))?,
420        )?;
421
422        let mut projected = Vec::with_capacity(seq * (DIM * (HC_MULT + 1)));
423        for token in 0..seq {
424            let input = &gathered[token * HASH_COLS * 256..(token + 1) * HASH_COLS * 256];
425            let mut row = vec![0.0f32; DIM * (HC_MULT + 1)];
426            engram.wkv.matvec(input, &mut row, None);
427            row.iter_mut().for_each(|v| *v = bf16_roundtrip(*v));
428            projected.extend_from_slice(&row);
429        }
430        compare_bf16(
431            &format!("layer={layer} case={case_no} projected"),
432            &projected,
433            &read_bf16(&projected_root.join(format!("layer-{layer}/case{case_no}_projected.bin")))?,
434        )?;
435
436        let input = read_bf16(&dir.join(format!("case{case_no}_input.bin")))?;
437        let expected_output = read_bf16(&dir.join(format!("case{case_no}_output.bin")))?;
438        let mask: Option<Vec<bool>> = if case["token_mask"].is_null() {
439            None
440        } else {
441            Some(serde_json::from_value(case["token_mask"].clone())?)
442        };
443        let mut output = Vec::with_capacity(input.len());
444        for token in 0..seq {
445            let mut h = input[token * HC_MULT * DIM..(token + 1) * HC_MULT * DIM].to_vec();
446            dsv41_apply_engram_for_test(
447                &engram,
448                &mut h,
449                &got_compact[token * HASH_COLS..(token + 1) * HASH_COLS],
450                &cfg(),
451                mask.as_ref().map(|m| m[token]).unwrap_or(true),
452            );
453            output.extend_from_slice(&h);
454        }
455        compare_bf16(
456            &format!("layer={layer} case={case_no} output"),
457            &output,
458            &expected_output,
459        )?;
460        println!(
461            "component layer={} case={} name={} compact_indices=true gathered=true projected=true output=true",
462            layer,
463            case_no,
464            case["name"].as_str().unwrap_or("?")
465        );
466    }
467    Ok(())
468}
Source

pub fn matvec2( &self, x1: &[f32], x2: &[f32], o1: &mut [f32], o2: &mut [f32], pool: Option<&Pool>, )

Fused two-input matvec (MTP verify pair): weights streamed once.

Source§

impl QTensor

Source

pub fn q4tp_mapped(&self) -> Option<(&Arc<CmfModel>, usize)>

Batched matvec (prefill-GEMM): xs — row-major [b, cols], out — row-major [b, rows]. Element-wise semantics are IDENTICAL to b matvec calls (same dot kernels in the same order); the win — the weight row streams from DRAM once per batch, not b times. (model, index) when this is a memory-mapped q4tp tensor — the identity a device-resident chain needs to hand tp_matmat the weight without going through this struct’s own dispatch.

Source

pub fn matmat( &self, xs_all: &[f32], b: usize, out: &mut [f32], pool: Option<&Pool>, )

Source§

impl QTensor

Source

pub fn device_matmat(&self, xs: &[f32], b: usize, out: &mut [f32]) -> bool

The device GEMM this tensor would take, run once on the caller’s data — the startup parity probe’s arm, and the one place that knows which entry point each codec has.

It exists because the probe used to look for a q4tp weight by name AND dtype, and a container packed any other way was declared “host path” for the whole render even though its codec had a device GEMM of its own. A gate that only recognizes one codec is a gate that silently downgrades every other one.

Source

pub fn matvec_many<const N: usize>( ts: [&QTensor; N], x: &[f32], outs: [&mut [f32]; N], pool: Option<&Pool>, )

Multi-matrix job (roadmap §3 P0): N tensors sharing one input run under a SINGLE pool dispatch — QKV or gate+up cost one barrier instead of N. Per-row math is the exact same kernel as matvec (bit-identical outputs); only the dispatch is fused. Falls back to N sequential matvecs when the set is not a uniform q8-family/F32 group or there is no pool.

Source§

impl QTensor

Source

pub fn matvec2_many<const N: usize>( ts: [&QTensor; N], x1: &[f32], x2: &[f32], o1s: [&mut [f32]; N], o2s: [&mut [f32]; N], pool: Option<&Pool>, )

Pair-input multi-matrix job: N tensors × 2 shared inputs under a single pool dispatch — the MTP/pair decode path publishes one job for Q/K/V (and one for gate+up) instead of one per tensor. Per-row math is exactly matvec2’s kernels; bit-identical.

Source

pub fn matvec_silu_mul( gate: &QTensor, up: &QTensor, x: &[f32], out: &mut [f32], pool: Option<&Pool>, ) -> bool

Fused gate+up matvec with SiLU·mul: for each row r, computes silu(gate·x) * (up·x) and writes to out[r]. ONE pool dispatch, no intermediate g/u buffers, no separate silu pass. Falls back (returns false) for unsupported dtype combos.

Source

pub fn matvec_silu_mul_limited( gate: &QTensor, up: &QTensor, x: &[f32], out: &mut [f32], limit: f32, pool: Option<&Pool>, ) -> bool

Fused gate+up+SiLU with the GLM asymmetrical clamp. limit == 0 preserves the historical unclamped helper; a positive limit clamps up to both sides and gate only from above, matching the GLM SwiGLU reference. Keeping the limit in the row kernel avoids the two intermediate vectors and the extra combine pass on the Q2TP experts.

Source

pub fn moe_gate_up_many( pairs: &[(&QTensor, &QTensor)], x: &[f32], outs: &mut [Vec<f32>], pool: Option<&Pool>, ) -> bool

Every routed expert’s fused gate/up/SiLU under ONE pool dispatch.

The per-expert path pays a pool barrier per expert per stage: at 9 experts over 40 layers that is ~720 barriers a token, and a decode profile of Qwen3.6-35B-A3B showed the pool parked in psynch_cvwait about twice as long as it spent computing. Laying every expert’s rows end-to-end in one virtual row space collapses the stage to a single dispatch. The per-row body is the single-expert q4tp arm verbatim, so outputs are bit-identical.

false = something is outside the fused q4tp kernel (dtype, shape, or the CMF_SDOT=0 exact contract); the caller walks the ordinary per-expert path.

Source

pub fn moe_down_many( downs: &[&QTensor], gs: &[Vec<f32>], weights: &[f32], out: &mut [f32], pool: Option<&Pool>, ) -> bool

Every routed expert’s down projection, weighted and summed into out, under ONE pool dispatch.

Partitioned by OUTPUT row rather than by expert: each row is owned by a single worker, so the experts are summed in the caller’s order — the same sequence of f32 adds the serial out[i] += w·eo[i] loop performs, hence bit-identical. Partitioning by expert instead would race on the shared accumulator.

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.

Source§

impl<T> Instrument for T

Source§

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

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

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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