Skip to content

mxfp4 kernels: replace the compute sink with real math (milestone 2) #2

Description

@rhCat

Milestone: mxfp4 kernels — replace the compute sink with real math

The structural milestone (see #1) is done: pointer map, trunk streaming, 3-phase cache, and the memory gate are validated on the 304B checkpoint (gate forecast 12.5 GB vs measured 11.92 GB; 0 dropped experts over 1,290 fetches). This milestone replaces the skeleton's checksum sink with real mxfp4 math, pipelined so reads and compute overlap.

Why now — the measured evidence

  • Threads sweep (4 → 20): 7.53 → 7.25 s/token. Flat. The wall is the synchronous loop + single-threaded compute sink, not read parallelism.
  • GB/token = 4.06, of which ~3.2 GB is expert bytes at FP8. The pool is 137 GB.
  • Replay on the real trace: compulsory ceiling 4.11%; LRU hits 0.00% at 2 GB — policy lesson already banked.

Consequence: two independent levers, both in this milestone:

  1. mxfp4 halves the expert bytes → ~68 GB pool, ~1.6 GB/token expert reads (the read-speed lever, invariant: 4-bit where streamed).
  2. Real threaded kernels + read/compute overlap → kills the sink wall (the threads sweep proves there is headroom).

Scope

1. Quantize pass (tools/convert-ds4f.py quantize)

  • Input: packed pool.bin (F8_E4M3 + per-tensor scales, copied as-is in the current convert) + tensor metadata (shapes from the safetensors index).
  • Output: pool-mxfp4.bin (E2M1, 4-bit, per-32-element block scale, MX-standard; scale = 8-bit E8M0 per block) + pool-mxfp4.json (block layout + per-expert error stats) + manifest update.
  • Deterministic; block-aligned; refuse on shape/dtype surprises (no guessing — same rule as the converter).
  • Quality gate: report per-expert max-abs and relative error vs the FP8 originals in the manifest. Numbers, not vibes.
  • Trunk (5.26 GB dense) stays at native precision — precision asymmetry invariant: full where resident, 4-bit where streamed.

2. Kernels (src/kernels.c + include/ds4f/kernels.h)

  • Scalar-correct mxfp4 first: unpack 32×4-bit block → fp32 × block scale → accumulate fp32. Portable C99.
  • Matvec path (M=1 decode): hidden/latent dims from config; per-expert w1/w2/w3 with their scales.
  • Router matvec: the resident high-precision router matrix (in trunk, layers.N.ffn.gate*) — small (hidden × 256), needed to produce real top-k.
  • SIMD after scalar is proven: AVX2 (x86) and NEON (arm64) paths, verified bit-identical against scalar on fixtures.
  • Threaded compute: per-expert matvecs across the topk batch.

3. Pipeline (src/main.c / trunk.c pattern reuse)

  • The trunk already has the async-reader pattern (ring + condvar). Extend it to experts: fetch layer L+1's top-k experts while computing layer L.
  • Decode loop becomes: bind trunk L (pinned or ring) → route (resident router) → overlapped expert fetch/compute → advance.
  • Multi-threaded checksum sink stays available via --sink for comparison runs.

4. Validation ladder (tests/)

  • Fixture: hand-built mxfp4 block with known values → decode → fp32 (bit-exact expected).
  • Quantize round-trip on synthetic FP8 tensors: error bounds asserted (not just reported).
  • Engine e2e with quantized synthetic pool: same request trace as FP8 run (routing independent of cache AND of dtype — invariant 2).
  • SIMD vs scalar equivalence on fixtures.

5. Acer validation run (paste back into this issue)

  • quantize the real pool (~68 GB out), then rerun the laptop-preset sweep.
  • Expected: GB/token ~2.1 (expert bytes halved), sec/token meaningfully lower (threaded + overlapped), RSS similar, 0 dropped.
  • If sec/token still flat, the wall moved — report it, don't tune around it.

Order of work

  1. quantize tool + manifest shapes (shapes already available in the converter's index)
  2. scalar mxfp4 decode + matvec + router (fixture-gated)
  3. pipeline restructure (async expert fetch)
  4. SIMD (AVX2/NEON) + equivalence gate
  5. real-pool quantize + acer sweep

Acceptance

  • quantize deterministic, block-aligned, error stats in manifest
  • scalar kernel bit-exact on fixture; SIMD == scalar on fixtures
  • --pool pool-mxfp4.bin runs end-to-end with real routing
  • acer: GB/token ≈ half of FP8 run, 0 dropped, report pasted here

Open decisions (flag in comments)

  • Expert tensor shapes (w1/w2/w3 dims) — resolve from the safetensors index during quantize; post the resolved shapes here before locking the kernel dimensions.
  • Block size 32 (MX default) vs 64 — 32 unless the error stats say otherwise.
  • Router placement: keep in trunk (resident when pinned) — confirm the gate tensor name from the index.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions