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

Labels

extractionMain extraction coming from rmems/corinth-canalmodularizationWork to make repos more modular and overlapping

Projects

Status
Backlog

Relationships

None yet

Development

No branches or pull requests

Issue actions