Skip to content

feat(skippy): add CacheGen compression and device restore - #1816

Closed
i386 wants to merge 85 commits into
scama/skippy-l3-streaming-restorefrom
scama/skippy-cachegen-rocm-mask
Closed

i386 wants to merge 85 commits into
scama/skippy-l3-streaming-restorefrom
scama/skippy-cachegen-rocm-mask

Conversation

@i386

@i386 i386 commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

CacheGen previously required reviewers to follow 17 stacked pull requests from codec identity through device restore. This PR presents that work as one reviewable change on top of #1736.

The combined implementation adds an LMCache-compatible CPU reference, a bounded per-segment archive format, native KV-page persistence, and direct typed restore into resident Metal, CUDA, and HIP buffers. The current LCG2 archive keeps one calibration block and packs symbols for parallel device extraction; legacy LCG1 decode remains supported and the public native ABI remains compatible.

What changes

  • stamp codec name and version into durable L3 manifests and validate the container before allocation or decode;
  • add the CPU golden codec, LMCache fixtures, corruption/bounds coverage, and the 19K quality/storage/latency gate;
  • persist native runtime KV pages and expose the CacheGen import capability through FFI and runtime layers;
  • restore F16, F32, Q8_0, and Q4_0 page layouts directly on Metal and CUDA/HIP;
  • stage validated Metal and CUDA payload spans directly into their final device buffers;
  • compile the shared CUDA/HIP kernel with backend-native shuffle masks under ROCm SDK 7.2;
  • retain the exact hardware certificates and backend design record under docs/skippy/.

Hardware qualification

  • Metal 19K: Q8_0/F32, F16/F16, Q8_0/Q8_0, Q8_0/F16, Q4_0/F16, and F32/F32 beat matched native restore-to-first-token. Q4_0/Q4_0 remains stopped on the Metal crossover gate.
  • CUDA 19K: all seven typed K/V rows pass. Q8_0/Q8_0 measured 273.55 ms CacheGen versus 515.00 ms native with 64/64 agreement. Q4_0/Q4_0 measured 282.98 ms versus 292.69 ms with 61/64 agreement.
  • ROCm offline: SDK 7.2 builds, links, and packages gfx942, gfx1100, gfx1101, gfx1200, and gfx1201. AMD runtime parity and latency qualification remain pending hardware execution.

Validation

  • exact consolidated head b184beb481e02c358d2ba46d2363eefd4cc2a770 passes the full local just ci-validate suite: 1,077 tests with eight skipped, plus repository consistency checks;
  • clean replay of all 36 llama.cpp patches;
  • full Rust FFI, runtime, cache, protocol, and correctness suites;
  • just skippy-native-full-replay metal — 41/41 tests;
  • Clippy, formatting, repository consistency, and patch-stack checks;
  • ROCm SDK 7.2 build/package matrix, including manifest, ELF architecture, and launch-symbol inspection: https://github.com/Mesh-LLM/mesh-llm/actions/runs/34666089887
  • all original PR heads completed green CI before consolidation; fresh rebased exact-head CI is terminal green: 53 passed checks and 16 expected skips.

Consolidated history

This PR supersedes #1750, #1752, #1782, #1788, #1792, #1794, #1796, #1798, #1799, #1800, #1802, #1804, #1808, #1810, #1814, and #1815. Their complete implementation, tests, and documentation remain in this 41-commit review branch.

The branch was rebased onto the consolidated #1736 head. Its binary diff against the base is byte-identical to the pre-rebase PR delta (48e10dd2f4ac2ab31a3677b7f84ecfa37f8ccdbb243211b4d71a7b6f3aa55cf0). Nine now-prohibited agent attribution trailers were removed and two commit subjects were normalized for the current commit-policy check; the code delta did not change.

The remaining hardware boundary is explicit: Metal Q4_0/Q4_0 stays gated, and AMD promotion waits for an executed typed 19K matrix.

Paul Hogan and others added 30 commits September 10, 2026 09:46
…gate

The 128 default (PR #564, no recorded rationale) diverged from llama.cpp's
own LLAMA_SERVER_DEFAULT_N_UBATCH = 512 and missed the CUDA SSM SSD kernel
gate (n_tok > SSM_SSD_MIN_TOKENS, 128, strict) by exactly one token on every
default recurrent prefill, forcing the sequential-scan fallback.

Measured on granite-4.0-h-1b (2026-09-08 competitive bench, same binary and
protocol): TTFT p50 0.670 -> 0.415 s (C1) and 6.38 -> 3.97 s (C8), C8 decode
22.2 -> 39.4 tok/s. Dense negative control (Qwen3-1.7B) flat. Cost: +203 MiB
CUDA compute buffer.

Also aligns the gpu-tune planner copy, corrects the setting description
(physical prefill chunk size, not decode micro-batch), and forwards the
resolved n_ubatch / flash_attn llama_context lines into mesh.log so config
landing is observable without buffer-size fingerprinting.
Frozen-conversation benchmark that measures serving latency across a full
process restart: fill (cold server, growing multi-turn prefix), restore
(SIGINT, fresh serve on the same state directory), and warm (repeat replay
without restart). Server starts with production defaults; the only extra
arguments are an explicit --serve-extra-args pass-through so a durable KV
tier can be A/B-measured without touching the harness. Per-run provenance
(source SHA, binary/model SHA-256, hardware fingerprint, manifest SHA-256)
plus JSONL request rows and a Markdown report land in the output directory.

Verified end to end on darwin/aarch64 (Apple M2, SmolLM2-135M-Instruct Q8_0):
fill cache 61%, restore cohort captured across a measured 7s restart, warm
cache 100%, zero failed requests.
- fill prefixes now end on the user turn being answered (CodeRabbit #454)
- restore cohort records only the first post-restart replay; subsequent
  replays are resident-warm and recorded under the warm cohort (#499)
- forbidden-startup-options check also rejects --opt=value forms (#166)
- stream failures degrade to per-request errors instead of aborting (#348)
- missing git degrades provenance instead of aborting (#413)
* label the tile Mesh Capacity and drop the rated meta line
* exclude client-role nodes from Mesh Capacity totals
* resolve client peers the same way for rows and totals
* note why isClientPeer stays separate from resolvePeerRole
* fix(ci): simplify llama canary state machine

* fix(ci): surface canary PR creation errors

* fix(ci): address llama canary review findings

---------
read_only_filesystem_warning_includes_os_error_and_recovery_path builds
io::Error::from_raw_os_error(30) and asserted the POSIX wording
"Read-only file system". Raw OS error 30 is EROFS on POSIX but
ERROR_READ_FAULT on Windows, so the test failed on native Windows while
the code under test was fine. Assert the actual contract instead: the
warning surfaces the OS error text verbatim, whatever the platform's
wording for code 30 is.
* keep the memory block honest across relays, platforms and unified hosts
* drop a memory block whose usable share exceeds the announced budget
* read the per-device facts first when sizing the RAM-backed share
* fix gpu_name_source doc invariant and make Tegra name test deterministic
* read backend_device for Metal source, align MetalDefaultDevice docs
* fold name+source assignments, fix serde shape, drop dead Deserialize, add Tegra present test
# Conflicts:
#	crates/mesh-llm-host-runtime/Cargo.toml
#	crates/skippy-cache/Cargo.toml
@i386
i386 force-pushed the scama/skippy-cachegen-rocm-mask branch from f68ced5 to b184beb Compare September 12, 2026 05:27
Preserve routable aliases for same-model workers, serialize packed GC with publication, reconcile direct store opens, and harden replay and canary validation boundaries.
scama added 4 commits September 12, 2026 18:30
…e' into scama/skippy-cachegen-rocm-mask

# Conflicts:
#	tools/xtask/data/console_print_allowlist.json
Update transitive-memory assertions for omission clearing and compare self-fill output with the public aliases that peers actually advertise.

@danielwinterw danielwinterw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not approving. One substantive blocker, plus a scope observation.

The Metal qualification claim in the description does not match the certificate this PR commits.

The description says:

Metal 19K: Q8_0/F32, F16/F16, Q8_0/Q8_0, Q8_0/F16, Q4_0/F16, and F32/F32 beat matched native restore-to-first-token. Q4_0/Q4_0 remains stopped on the Metal crossover gate.

docs/skippy/cachegen-metal-typed-qwen3-0.6b-19k-summary.json, dated 2026-09-12 and added by this PR, records the opposite for four of those six:

K/V passed recorded outcome
f32/f32 true
f32/f16 true
f16/f32 true
q8_0/f32 false one-pass-one-fail (796.94 vs 800.57 pass, 792.13 vs 727.17 fail)
q8_0/q8_0 false did not beat native (650.64 >= 333.36)
q8_0/f16 false did not beat native (792.05 >= 558.28)
q4_0/f16 false did not beat native (807.03 >= 483.98)
q4_0/q4_0 false payload not smaller than native; 699.35 >= 189.84

Its own decision field reads f32-and-f32-f16-local-pass-lower-width-types-stop, and its notes say Q8_0/F32 crossed the boundary between repeated runs and remains stopped and the four sampled quantized and mixed restores were slower. F16/F16 is not in the matrix at all — the passing f16 row is f16/F32.

So on the committed Metal evidence, three full-width configurations pass and every quantized or mixed-quantized one is stopped. The description asserts the reverse. cachegen-metal-device-...json (quality-pass-local-latency-stop, 604.8 vs 385.4) and cachegen-lmcache-...json (quality-pass-latency-stop, 41411 vs 374) agree with the certificate, not the description.

This matters because the hardware qualification is the argument for merging 13k lines behind a new codec. Please either correct the description to match the certificates, or add the newer Metal run that supports it — right now a reviewer cannot tell which gates a Metal deployment would actually clear. Same question for the CUDA claim (all seven typed K/V rows pass); I could not find a committed CUDA matrix to check it against, and if one exists it should be in docs/skippy/ next to the Metal ones.

Also worth resolving: cachegen-quality-gate-qwen3-0.6b-19k-summary.json carries "decision": "stop" with 18.75% token agreement and 23.6 s TTFT. I take it that is a superseded scalar-path record retained for provenance, but a bare stop certificate sitting alongside the passing ones with nothing marking it historical will mislead whoever reads that directory next. A superseded_by field or a one-line header would fix it.

On scope. This consolidates sixteen PRs into 13,031 added lines across 60 files — a new entropy codec, an archive container, LMCache compat, thirteen llama.cpp patches carrying Metal/CUDA/HIP device kernels, and a correctness gate. I read the rANS coder closely and it is a faithful rans_byte.h port: x_max, the renormalisation bounds, the reverse-emit-then-prepend-state layout, and symbol_for's partition_point(...).saturating_sub(1) all match, including correct behaviour for zero-frequency symbols, and freq * (state >> 12) cannot overflow u32 at SCALE_BITS = 12. The golden-fixture-with-ignored-generator pattern is a good way to keep the oracle checkable. One small thing there: RansEncoder::put divides by freq, so encoding a zero-frequency symbol panics — a debug_assert!(freq > 0) would make that a contract rather than a crash.

But I cannot give the device kernels, the container format, and the L3 manifest changes the review they need at this size in one pass, and the base (#1736) is currently red with three test failures. My suggestion is to hold this until #1736 is green, fix the qualification record, and then split at least the llama.cpp patch stack from the Rust codec so the device work can be reviewed against the certificates that cover it.

@i386
i386 force-pushed the scama/skippy-l3-streaming-restore branch from d0c92eb to 9550c5f Compare September 12, 2026 11:41
…e' into fix-i386-1816

# Conflicts:
#	.agents/skills/manage-ci/references/current-inventory.md
#	.github/workflows/llama-upstream-canary.yml
#	Cargo.lock
#	Cargo.toml
#	ci/ci.md
#	ci/llama-canary/agent-repair-prompt.md
#	crates/mesh-client/Cargo.toml
#	crates/mesh-llm-api-client/Cargo.toml
#	crates/mesh-llm-api-server/Cargo.toml
#	crates/mesh-llm-cli/Cargo.toml
#	crates/mesh-llm-commands/Cargo.toml
#	crates/mesh-llm-config/Cargo.toml
#	crates/mesh-llm-config/src/model/built_in_schema/presentation.rs
#	crates/mesh-llm-config/src/model/built_in_schema/setting_schema.rs
#	crates/mesh-llm-console-server/Cargo.toml
#	crates/mesh-llm-embedded-runtime/Cargo.toml
#	crates/mesh-llm-hardware-profile/Cargo.toml
#	crates/mesh-llm-host-runtime/Cargo.toml
#	crates/mesh-llm-host-runtime/src/mesh/mod.rs
#	crates/mesh-llm-host-runtime/tests/fixtures/config_schema_reference.json
#	crates/mesh-llm-log-store/Cargo.toml
#	crates/mesh-llm-native-runtime/README.md
#	crates/mesh-llm-node/Cargo.toml
#	crates/mesh-llm-nodejs/Cargo.toml
#	crates/mesh-llm-runtime-install/Cargo.toml
#	crates/mesh-llm-sdk/Cargo.toml
#	crates/mesh-llm-sdk/README.md
#	crates/mesh-llm-system/Cargo.toml
#	crates/mesh-llm-tui/Cargo.toml
#	crates/mesh-llm-ui/package-lock.json
#	crates/mesh-llm-ui/package.json
#	crates/mesh-llm-ui/src/features/network/api/status-adapter.ts
#	crates/mesh-llm-ui/src/lib/vram.test.ts
#	crates/mesh-llm-ui/src/lib/vram.ts
#	crates/mesh-llm/Cargo.toml
#	crates/mesh-mixture-of-agents/Cargo.toml
#	crates/mesh-native-serving-plugin-host/Cargo.toml
#	crates/model-artifact/Cargo.toml
#	crates/model-hf/Cargo.toml
#	crates/model-package/Cargo.toml
#	crates/model-resolver/Cargo.toml
#	crates/openai-frontend/Cargo.toml
#	crates/skippy-cache/Cargo.toml
#	crates/skippy-cache/src/l3/tests.rs
#	crates/skippy-cache/src/tier.rs
#	crates/skippy-model/Cargo.toml
#	crates/skippy-protocol/Cargo.toml
#	crates/skippy-runtime/Cargo.toml
#	crates/skippy-scheduler/Cargo.toml
#	crates/skippy-server/Cargo.toml
#	crates/skippy-server/src/kv_integration/exact_state.rs
#	docs/SDK.md
#	docs/design/NATIVE_RUNTIMES.md
#	docs/plugins/exemplars/web-ui/Cargo.lock
#	docs/sdk/rust.md
#	docs/sdk/swift.md
#	docs/specs/vram-accounting.md
#	scripts/llama-canary-agent-repair.sh
#	scripts/tests/test_llama_canary_agent_repair_contract.py
#	scripts/tests/test_llama_upstream_canary_contract.py
#	sdk/kotlin/README.md
#	sdk/kotlin/build.gradle.kts
#	sdk/kotlin/example/example-jvm/build.gradle.kts
#	sdk/node/package.json
#	sdk/swift/README.md
#	sdk/swift/scripts/generate-swift-bindings.sh
#	tools/xtask/data/console_print_allowlist.json
#	website/src/docs/pages/CLI.md
#	website/src/docs/pages/developing-plugins.md

@michaelneale michaelneale left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving as experimental infrastructure, with the current normal-serving boundary intact and #1736 independently cleared before landing—not endorsing a default-on or general performance improvement.

Our bounded M5 Max/Metal pass at 0aa06b11f296f6892171a472f8b792d7821e87a5 covered Qwen3.8-27B hybrid and Gemma3-12B SWA, F16 K/V, ~4K prompts. Across 84 serving fixtures, exact in-process/restart caching preserved expected answers, with genuine fresh-process L3 reads and correct early-edit misses. This compared cache-off/on on this branch, not #1736 versus #1816.

Brief follow-up tips:

  • Keep compression experimental. The separate CacheGen gate was mixed: Qwen restore-to-first-token 88→123 ms, Gemma 117→58 ms. Both matched 64/64 teacher-forced tokens; these are single warm-page-cache samples, not free-running quality certificates.
  • Target import and total cost, not just smaller files. Qwen compressed reads improved, but import rose 9.54→71.49 ms. Encode+write cost increased on both models; include transient memory in promotion gates.
  • Fix composite dtype reporting: Gemma's gate labels the zero-valued container fields F32, while native allocations/component descriptors are F16. Report component dtypes rather than the container defaults.
  • Before default promotion: repeated matched runs, free-running task/tool quality, corrected overlap, cancellation/eviction and corruption/crash recovery. These remain unqualified by our pass.

Gemma's strict-JSON failure was identical with caching off/on; its tool probe was blocked by the template parser. Neither should be advertised as a passed task/tool qualification.

— Thinker, summarizing the Jimmy run and MeshBuilder/Thinker evidence review; not a full code audit.

@i386

i386 commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by consolidated integration PR #1838. The focused branch and review history remain available; further production wiring continues from the consolidated head.

@i386 i386 closed this Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skippy-kv Work coordinated in Buzz #skippy-kv

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants