Skip to content

gguf: optional mmap-backed reader + K-quant dequant (blocks the corinth-canal consumer) #45

Description

@rmems

Mirror of rmems/corinth-canal#144. Follow-up to the closed #7; blocks rmems/corinth-canal#115.

Why this exists

#7 ("adopt/enhance as canonical GGUF parser by extracting from corinth-canal") is closed as Done,
but its sibling on the consumer side — rmems/corinth-canal#115, "migrate GGUF parser layer to
engram-parser dep" — is not implementable against v0.2.0. The extraction landed; the adoption
cannot follow. Filing so that gap is tracked somewhere rather than sitting invisible behind a
closed issue.

Blocker 1 — whole-file read vs mmap

src/gguf/mod.rs:38-45:

/// The full file contents are read into memory (no mmap; zero-dep by design)
...
let bytes = fs::read(path_ref).map_err(|e| ParserError::Io { ... })?;

GgufLayout owns a Vec<u8> of the entire checkpoint.

corinth does the opposite and has to: it mmaps the file (src/moe/gguf/map.rs) and then
CUDA-host-registers page-aligned tensor ranges (src/moe/gguf/cuda_register.rs) so the GPU can
DMA directly from the mapping. These are multi-GB MoE checkpoints — 8.9 GB ZAYA1-8B-Q8_0, 14 GB
Kimi-VL-A3B-Q6_K, and larger. Reading them into an owned Vec<u8> is not a performance nuance; it
defeats the purpose of the mapping layer and would make host-register impossible.

I recognise [dependencies] is deliberately empty and that memmap2 contradicts the zero-dep
stance. That is exactly why this needs a decision rather than a patch.

Blocker 2 — F16-only dequantization

$ grep -rn "pub fn dequantize" src/
src/gguf/tensor.rs:504:    pub fn dequantize_f16(&self, bytes: &[u8]) -> Result<Vec<f32>>

corinth needs Q8_0, Q5_K, Q6_K, and IQ3_M (src/moe/gguf/map.rs, src/moe/gguf/dequant.rs) —
that ladder is the entire basis of its synapse-source selection, and the local model inventory is
predominantly Q8_0/Q6_K.

Why header-only adoption isn't a useful compromise

Taking this crate for just header/KV/tensor-directory parsing would replace corinth's
src/moe/gguf/metadata.rs — about 335 lines — with a dependency that reads the whole checkpoint
into RAM in order to parse a header
. Strictly worse than the status quo.

Options

  1. Optional mmap feature (default off, zero-dep path preserved) plus K-quant dequant behind a
    feature or in the core. Keeps the crate's stated design intact for existing users while making a
    real consumer possible.
  2. Decline, and record that engram-parser is zero-dep by construction and will not serve
    mmap-backed consumers. Then moe: migrate GGUF parser layer to engram-parser dep (extract useful code from experimental ref impl) corinth-canal#115 should be closed won't-do, and sharing
    happens the [engram-parser] GH#10 — safetensors: coordinate ecosystem / sibling parser extraction from corinth-canal (separate from GGUF #7; one-way copy, no dep on corinth-canal) #10 way — one-way copy, no dependency. That is a legitimate outcome; [engram-parser] GH#10 — safetensors: coordinate ecosystem / sibling parser extraction from corinth-canal (separate from GGUF #7; one-way copy, no dep on corinth-canal) #10 already
    establishes that pattern for safetensors.

Either is fine. What is not fine is #115 sitting open indefinitely against an API that cannot
satisfy it.

Acceptance

Context

Part of a three-repo dependency review this week; all three reached the same shape — the influence
gradient runs corinth → siblings, so upstream first, adopt second. See
rmems/corinth-canal#143 (axon-encoder / neuromod), #144 (this), #145 (myelin-accelerator, mirrored
as Limen-Neural/myelin-accelerator#27).

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiAPI changes or trait workextractionmodularizationWork to make repos more modular and overlapping

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions