Skip to content

docs(adr): ADR-075 — MoE expert-offload priority (Metal)#727

Merged
oceanwaves630 merged 2 commits into
mainfrom
docs/adr-075-moe-offload-priority
Jul 9, 2026
Merged

docs(adr): ADR-075 — MoE expert-offload priority (Metal)#727
oceanwaves630 merged 2 commits into
mainfrom
docs/adr-075-moe-offload-priority

Conversation

@oceanwaves630

Copy link
Copy Markdown
Collaborator

PR description authored by Claude (Anthropic agent) on behalf of @oceanwaves630.

ADR-075 — MoE expert-offload priority (Metal)

Fifth sequencing ADR in the bundle set, after ADR-071 (GDN-state), ADR-072 (weight-quant), ADR-073 (KV-quant), ADR-074 (MTP). Docs-only.

Verdict: NEEDS-EXPERIMENT, reframed — gated, not ranked

The question as commissioned — rank the open MoE expert-offload levers — presupposes a working, measured, resident MoE serving path whose next optimization is offload. That precondition is false on the current head, and the reasons are the finding.

Load-bearing facts (all verified against origin/main @ c9ae21a9):

  • Lattice ships exactly one MoE preset (qwen36_35b_a3b). The large model it actually serves and has measured (~4 tok/s) is qwen36_27b, which is dense — so no measured number this engine has ever produced touches MoE.
  • The Metal MoE dispatch (ADR-053, merged PR feat(inference): MoE Metal dispatch with expert coalescing (ADR-053) #57) is wired into the live forward loop but has zero test/bench/measurement (encode_moe_ffn has one production call site, appears in no test), and runs only at f16 — Q4/QuaRot, Q8-CPU, and Q8-NEON all three explicitly refuse MoE.
  • The engine constructor takes a fully-loaded &ModelWeights, so the CPU loader materializes the full model as f32 (~120 GiB) before any Metal buffer is built — a loader-sequencing ceiling that makes the model not loadable on any consumer Apple Silicon today, independent of offload.

Measured correction of a merged ADR (ADR-053)

ADR-053 quotes "~15 GiB" resident routed-expert weights and reasons its 32 GB feasibility from it — but it says "At Q4 with the current config dimensions," and Q4 was never implemented for MoE (the three refusal points above). The only precision that runs is f16, so the real resident footprint is 60 GiB — 4× the ADR-053 figure. This is recorded as an amendment here (ADR-053 stays an immutable record); its dispatch/routing design is unaffected, only its resident-memory arithmetic and the "borderline on 32 GB" claim are corrected (it's not borderline — it doesn't fit).

Structure

A Measured / source-verified reality table (E1–E12, each tagged source-read / unit-test-pinned / runtime-measured with a durable pointer) plus a derived memory-arithmetic table, held apart from an untrusted external prior-art survey that is confirmed repo-blind (targets a nonexistent crates/engine crate and a GGUF loader lattice doesn't have) and scoped to a different model family (DeepSeek-V4-Flash). The survey's arithmetic is unranked until re-derived on lattice's real 6.0 MiB/expert f16 numbers; its one convergent conclusion (build and measure the resident dispatch before adding disk streaming) matches the source-read verdict.

Decision

Gates the whole offload family (#682 the literal lever, #686 the epic, FP4 #683 / FP8 #684 adjacent) behind a minimal experiment:

  • Step 0: confirm the loader-sequencing ceiling (instrument an actual MoE-preset load); if confirmed, fixing it (stream layer-by-layer) lowers the memory floor before any offload code.
  • Step 1: drive a synthetic small MoE (4 layers, 16 experts) through the real MetalQwen35Engine for the first-ever measured MoE dispatch correctness + latency, under GPU flock, committed as an artifact.
  • Step 2: only then re-derive the offload hit-rate arithmetic on real numbers, at which point MoE expert weight offloading: run models larger than RAM by streaming cold experts from disk #682's design becomes decidable.

Honest framing: this is not "REFUTED — wrong architecture" (MoE exists and is wired); it's "the lever is real, but the measurement floor beneath it does not exist yet." Includes a forward instruction (mirroring ADR-074's rider): when Step 1's bench lands, its numbers amend both this ADR's table and ADR-053's corrected figure with runtime-measured rows.

Testing

Docs-only. No executable behavior changes.

oceanwaves630 and others added 2 commits July 9, 2026 03:45
Fifth sequencing ADR in the bundle set (siblings ADR-071/072/073/074).
Verdict NEEDS-EXPERIMENT, reframed: ranking expert-offload presupposes a
working, measured, resident MoE serving path to offload from, and that
precondition is false on the current head. The single MoE preset
(qwen36_35b_a3b) is source-verified not loadable on any consumer Apple
Silicon today; its Metal dispatch (ADR-053/#57) is wired but has zero
test/bench/measurement and runs only at f16 (Q4/Q8 all refuse MoE at
three enforcement points). Records a measured correction of ADR-053: its
"~15 GiB @ Q4" resident figure is 4x under — the real f16 footprint is
60 GiB — because the Q4 MoE basis was never implemented. Gates the whole
offload family behind a minimal synthetic-MoE dispatch bench (first real
MoE tok/s on this engine) plus a loader-sequencing confirmation, before
any offload code. Untrusted external survey folded (repo-blind, scoped to
DeepSeek-V4-Flash, arithmetic unranked until re-derived on real numbers).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…E2 fallback, source-derived wording

Applies codex R1 (APPROVE-WITH-FIXES) findings:
- M1: narrow "not loadable on any consumer Apple Silicon" → the 32-128 GB
  M-series/M-Max class; Ultra-class desktops (192-512 GB) could hold the
  ~180 GiB peak, unproven until Step 0 measures it (3 sites).
- M2: E2 "every binary falls back to qwen36_27b" → path-specific dense
  defaults (Q4→27b, safetensors→2b, benches→0.8b); MoE preset selected by
  no default (verified vs origin/main lattice.rs:1061/1076, model.rs:37-42).
- M3: survey repo-blindness reframed onto repository-verifiable absences
  (no crates/engine, no GGUF, no such binaries — grep-confirmable); packet
  quotes demoted to corroboration.
- minor: "measured correction" → "source-derived correction" (the 60/120
  GiB figures are derived arithmetic, not runtime-measured).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@oceanwaves630 oceanwaves630 marked this pull request as ready for review July 9, 2026 08:09
@oceanwaves630 oceanwaves630 enabled auto-merge (squash) July 9, 2026 08:09

@ohdearquant ohdearquant left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SPEC-GATE: SIGNED (Leo). The reframe is the honest verdict: 'gated, not ranked' is correct when the resident path beneath every offload lever has never produced a token, and refusing to rank on a repo-blind survey scoped to a different model family is exactly right. The ADR-053 amendment is the house pattern done well — immutable record untouched, only the memory arithmetic and 32GB-feasibility corrected, with the causal mechanism (ADR-044 deferral enforced in the converter, no MoE quantizer ever landed) rather than a bare number. The codex-narrowed loadability claim (not loadable on 32-128 GB M-series/M-Max; Ultra-class unproven pending Step 0) survives my read at all three sites. Rider: Step 0's result lands as a new S-row on this ADR whichever way it goes — if from_safetensors turns out to stream internally, the 120 GiB peak claim gets corrected the same way this ADR corrected ADR-053. Proceed to G on merge.

@oceanwaves630 oceanwaves630 merged commit 4cb006d into main Jul 9, 2026
24 checks passed
@oceanwaves630 oceanwaves630 deleted the docs/adr-075-moe-offload-priority branch July 9, 2026 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants