mlx-bun 0.0.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -578
- package/bin/mlx-bun.mjs +1 -1
- package/docs/README.md +91 -0
- package/docs/{design → archive}/hlg-sampling.md +3 -3
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
- package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
- package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
- package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
- package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
- package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
- package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
- package/docs/design/batching.md +569 -0
- package/docs/design/decode-speed-program.md +3178 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +579 -334
- package/docs/design/kv-cache.md +680 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1627 -0
- package/docs/design/turboquant.md +2102 -0
- package/docs/design/unified-engine-frontier-plan.md +1831 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +34 -1
- package/docs/planning/release-notes-v0.3.0.md +35 -0
- package/docs/planning/video-series.md +421 -0
- package/docs/reference/benchmarks.md +1162 -0
- package/docs/reference/cli.md +395 -149
- package/docs/reference/distribution.md +321 -181
- package/docs/reference/environment.md +348 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +580 -142
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +137 -6
- package/docs/reference/server-api.md +938 -422
- package/docs/reference/server-config.md +652 -320
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +166 -0
- package/package.json +10 -5
- package/src/admission-plan.ts +18 -0
- package/src/anthropic.ts +92 -3
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1646 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +47 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/gateway-binding.ts +71 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/memory-client.ts +189 -0
- package/src/backends/mlx/memory-guard.ts +40 -0
- package/src/backends/mlx/methods.ts +90 -0
- package/src/backends/mlx/model-prompt.ts +164 -0
- package/src/backends/mlx/model-serving.ts +79 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/rollback.ts +51 -0
- package/src/backends/mlx/serial-executor.ts +273 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-views.ts +26 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/cli.ts +189 -61
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +49 -0
- package/src/contracts/generation.ts +103 -0
- package/src/contracts/host.ts +7 -0
- package/src/contracts/jobs.ts +66 -0
- package/src/contracts/pi-provider.ts +30 -0
- package/src/contracts/pi.ts +259 -0
- package/src/contracts/resources.ts +18 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/contracts/tsconfig.json +14 -0
- package/src/diffusion/diffusion-generate.ts +218 -153
- package/src/embed.ts +1 -1
- package/src/engine/admission.ts +59 -0
- package/src/engine/cancellation.ts +38 -0
- package/src/engine/engine.ts +56 -0
- package/src/engine/execution-coordinator.ts +70 -0
- package/src/engine/execution-plan.ts +51 -0
- package/src/engine/resources.ts +42 -0
- package/src/engine/scheduler.ts +67 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +263 -23
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +10 -79
- package/src/eval/tasks/bfcl.ts +2 -1
- package/src/eval/tasks/gsm8k.ts +2 -1
- package/src/eval/tasks/hashhop.ts +2 -1
- package/src/eval/tasks/humaneval.ts +5 -4
- package/src/eval/tasks/ifeval.ts +2 -1
- package/src/eval/tasks/mmlu.ts +2 -1
- package/src/expert-io.ts +3 -1
- package/src/expert-offload.ts +3 -1
- package/src/fill/echo-index.ts +188 -0
- package/src/fill/fill-session.ts +452 -0
- package/src/fill/proposal.ts +68 -0
- package/src/fill/schema-rows.ts +506 -0
- package/src/fill/tool-boundary.ts +103 -0
- package/src/fit.ts +24 -43
- package/src/generate.ts +740 -337
- package/src/grammar.ts +14 -8
- package/src/harness-pi.ts +15 -34
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +27 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/graph.ts +33 -0
- package/src/inference/prefill.ts +39 -0
- package/src/inference/rollback.ts +7 -0
- package/src/jobs/db.ts +4 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-entry.ts +15 -14
- package/src/jobs/runner.ts +98 -13
- package/src/jobs/task-client.ts +19 -0
- package/src/jobs/types.ts +2 -58
- package/src/kv-scheme.ts +199 -0
- package/src/kv-store.ts +459 -234
- package/src/lab/README.md +18 -0
- package/src/{assets → lab/curve}/curve-designer.html +2 -2
- package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
- package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
- package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +20 -4
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +32 -170
- package/src/memory/prompts.ts +1 -1
- package/src/memory/rest.ts +1 -1
- package/src/memory/schedule.ts +1 -1
- package/src/memory/stages.ts +4 -1
- package/src/memory/vault.ts +3 -4
- package/src/mlx/array.ts +9 -10
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +66 -22
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +64 -19
- package/src/mlx/quantized-rows.ts +36 -0
- package/src/mlx/token-bitmask.ts +52 -0
- package/src/mlx/turboquant-kv-decode.ts +82 -0
- package/src/mlx/turboquant-kv-inverse.ts +122 -0
- package/src/mlx/turboquant-ops.ts +33 -3
- package/src/mlx/turboquant-tables.ts +2 -2
- package/src/model/batched-mask.ts +9 -3
- package/src/model/batched-quant.ts +2 -2
- package/src/model/batched-rotating-quant.ts +45 -99
- package/src/model/batched-rotating-state.ts +73 -0
- package/src/model/batched-rotating.ts +57 -106
- package/src/model/batched-row-storage.ts +127 -0
- package/src/model/compiled-decode.ts +4 -3
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +87 -49
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/gemma4-base.ts +187 -17
- package/src/model/gemma4.ts +6 -6
- package/src/model/generated/gemma4-12b.ts +52 -148
- package/src/model/generated/gemma4-26b.ts +34 -94
- package/src/model/generated/gemma4-e4b.ts +28 -76
- package/src/model/glm52-cache.ts +19 -9
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +28 -1
- package/src/model/implementation.ts +69 -0
- package/src/model/minicpm5.ts +7 -8
- package/src/model/profile.ts +443 -0
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta.ts +98 -2
- package/src/model/qwen3-mrope.ts +252 -0
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +336 -60
- package/src/model/support.ts +1 -1
- package/src/model/trellis-balanced-scatter.ts +51 -0
- package/src/model/trellis-linear.ts +672 -0
- package/src/model/trellis-shared-m.ts +151 -0
- package/src/model/trellis-shared-scatter.ts +144 -0
- package/src/model/trellis-splitk-prefill.ts +158 -0
- package/src/model/trellis-tiled-prefill.ts +136 -0
- package/src/model/trellis-vector-expand.ts +62 -0
- package/src/model/trellis-wide-prefill.ts +94 -0
- package/src/model/universal/dense.ts +1 -1
- package/src/model/universal/modules.ts +8 -1
- package/src/native/frame_extract.swift +140 -0
- package/src/native-pack.ts +15 -7
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +14 -320
- package/src/prompt-cache.ts +97 -54
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/atomic-output.ts +38 -0
- package/src/quantize/calibration.ts +2 -1
- package/src/quantize/config-writer.ts +16 -3
- package/src/quantize/index.ts +28 -1
- package/src/quantize/job.ts +11 -0
- package/src/quantize/quantizer.ts +265 -100
- package/src/quantize/rotate.ts +603 -0
- package/src/quantize/safetensors-writer.ts +79 -1
- package/src/quantize/sensitivity.ts +41 -59
- package/src/quantize/trellis.ts +586 -0
- package/src/quantize/weight-transform.ts +292 -0
- package/src/responses.ts +130 -3
- package/src/runtime-config.ts +81 -0
- package/src/sampler.ts +276 -4
- package/src/serve/admin-routes.ts +184 -0
- package/src/serve/aux-routes.ts +132 -0
- package/src/serve/batch-scheduler.ts +8 -1558
- package/src/serve/chat-request.ts +391 -0
- package/src/serve/chat-stage.ts +195 -0
- package/src/serve/checkpoint-identity.ts +64 -0
- package/src/serve/completion-executor.ts +354 -0
- package/src/serve/completion-sink.ts +157 -0
- package/src/serve/discovery-routes.ts +204 -0
- package/src/serve/generation-gateway.ts +211 -243
- package/src/serve/http.ts +159 -0
- package/src/serve/inference-request.ts +79 -0
- package/src/serve/isolate.ts +297 -105
- package/src/serve/kv-budget.ts +14 -0
- package/src/serve/lab-routes.ts +341 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +155 -0
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +512 -0
- package/src/serve/openai-wire.ts +103 -0
- package/src/serve/parent-application.ts +56 -0
- package/src/serve/pipeline.ts +33 -0
- package/src/serve/preparation.ts +33 -0
- package/src/serve/prompt-response-trace.ts +147 -0
- package/src/serve/request-plan.ts +162 -0
- package/src/serve/request-prep.ts +346 -0
- package/src/serve/response-lease.ts +24 -0
- package/src/serve/responses-client.ts +69 -0
- package/src/serve/session-completion-engine.ts +110 -0
- package/src/serve/session-search.ts +1 -1
- package/src/serve/static-routes.ts +101 -0
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +523 -3551
- package/src/spec/assistant-source.ts +10 -44
- package/src/spec/deepspec-source.ts +6 -6
- package/src/spec/dflash-source.ts +9 -8
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +2 -2
- package/src/spec/dspark/generate-dflash.ts +2 -2
- package/src/spec/dspark/generate.ts +2 -2
- package/src/spec/dspark/loader.ts +1 -1
- package/src/spec/dspark/module-dflash.ts +5 -4
- package/src/spec/dspark/module.ts +3 -3
- package/src/spec/dspark/quantize-drafter.ts +1 -1
- package/src/spec/generate.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +9 -1
- package/src/spec/ngram-source.ts +1 -1
- package/src/spec/prefix-state.ts +45 -0
- package/src/spec/qwen-mtp-source.ts +528 -0
- package/src/spec/serve-loop.ts +179 -213
- package/src/spec/source.ts +42 -10
- package/src/spec/two-model.ts +1 -1
- package/src/ssd-cache.ts +95 -24
- package/src/ssd-durability.ts +207 -0
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +14 -13
- package/src/train/forward.ts +38 -1
- package/src/train/loss.ts +3 -2
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +9 -6
- package/src/train/trainer.ts +9 -8
- package/src/vision/preprocess.ts +1 -1
- package/src/vision/prompt.ts +48 -2
- package/src/vision/qwen3vl-preprocess.ts +409 -0
- package/src/vision/qwen3vl-prompt.ts +196 -0
- package/src/vision/qwen3vl-tower.ts +555 -0
- package/src/vision/video-frames.ts +148 -0
- package/src/web/app.html +1 -1
- package/src/web/app.js +15 -6
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +16 -9
- package/src/web/src/composer.ts +4 -4
- package/src/web/src/hub.ts +1 -1
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +1 -1
- package/src/web/src/model-picker.ts +1 -1
- package/src/web/src/palette.ts +1 -1
- package/src/web/src/protocol.ts +3 -39
- package/src/web/src/sessions.ts +1 -1
- package/src/web/src/ui-catalog.ts +4 -18
- package/src/web-assets.ts +47 -0
- package/src/weights.ts +134 -33
- package/docs/archive/mlx-bun-lab-report.html +0 -275
- package/docs/archive/wwdc-mlx-bun.html +0 -848
- package/docs/design/adapters-end-to-end.md +0 -205
- package/docs/design/batching-perf-path.md +0 -255
- package/docs/design/batching-v2-plan.md +0 -529
- package/docs/design/bucketing-stage.md +0 -197
- package/docs/design/compat-cli-surface-design.md +0 -230
- package/docs/design/docs-reorg-plan.md +0 -165
- package/docs/design/dspark-serving-program.md +0 -371
- package/docs/design/dspark-speculative-decoding.md +0 -268
- package/docs/design/grammar-spec-batching-integration.md +0 -301
- package/docs/design/memory-inference-path.md +0 -422
- package/docs/design/memory-synthesis.md +0 -287
- package/docs/design/memory-system.md +0 -237
- package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
- package/docs/design/omlx-adoption-map.md +0 -98
- package/docs/design/orpo-dynamic-lambda.md +0 -220
- package/docs/design/orpo-future-enhancements.md +0 -340
- package/docs/design/paged-kv-cache.md +0 -214
- package/docs/design/parallel-slots.md +0 -567
- package/docs/design/parity-tier-dag.md +0 -161
- package/docs/design/repo-cleanup-plan.md +0 -189
- package/docs/design/runtime-isolation.md +0 -263
- package/docs/design/segmented-backward-training.md +0 -543
- package/docs/design/spec-decode-larger-targets.md +0 -229
- package/docs/design/ssd-kv-cold-tier.md +0 -288
- package/docs/design/structured-output.md +0 -484
- package/docs/design/tauri-desktop-app.md +0 -127
- package/docs/design/the-dreaming-master-plan.md +0 -445
- package/docs/design/turboquant-kv.md +0 -235
- package/docs/design/w4a16-compute-precision-spike.md +0 -232
- package/docs/design/web-chat-beat-matrix.md +0 -315
- package/docs/design/write-pipeline-entity.md +0 -468
- package/docs/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/investigations/hlg-ab.html +0 -34
- package/docs/investigations/hlg-explorer.html +0 -238
- package/docs/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/investigations/hlg-figs/cross.svg +0 -1
- package/docs/investigations/hlg-figs/edges.svg +0 -1
- package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/investigations/hlg-report.html +0 -262
- package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- package/docs/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -100
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -13
- /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
- /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
- /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
- /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
- /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
- /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
- /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
- /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
- /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
- /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
- /package/docs/{planning → archive/planning}/journal.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
- /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
- /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
# TurboQuant KV — design (Phase 13)
|
|
2
|
-
|
|
3
|
-
Status: v1 wired end-to-end (2026-07-06): codec + `TurboQuantKVCache` +
|
|
4
|
-
`--kv-quant turbo[:k<bits>v<bits>]` (cli.ts, serve/generate/bench) +
|
|
5
|
-
`maybeQuantizeKv` conversion + `GenerationGateway` solo-only refusal +
|
|
6
|
-
`kv-store.ts` persistence + `scripts/eval-turboquant-curve.ts` (KL/ppl curve
|
|
7
|
-
script; not yet RUN against a real model — that's the next stage's gate).
|
|
8
|
-
Owner seam: L2 cache format, L1-unmodified attention (dequantize-on-fetch),
|
|
9
|
-
eval-gated. Opt-in only — naked default stays L1.
|
|
10
|
-
|
|
11
|
-
## What it is
|
|
12
|
-
|
|
13
|
-
Rotation-based KV-cache quantization: signed int8 affine keys + FWHT-rotated
|
|
14
|
-
3-bit Lloyd-Max values, per-32-group fp16 scales. More usable context at the
|
|
15
|
-
same memory (2.56× KV compression at the k8/v3 default, head_dim 128), NOT a
|
|
16
|
-
weight quantizer. Composes with (is orthogonal to) the per-layer mixed-KV
|
|
17
|
-
allocation axis — TurboQuant is the QUANTIZER axis (frontier plan §7.2).
|
|
18
|
-
|
|
19
|
-
## Oracle chain (decided 2026-07-06 from the research fan-out)
|
|
20
|
-
|
|
21
|
-
Two unrelated implementations share the name; do not conflate:
|
|
22
|
-
|
|
23
|
-
- **The paper** (arXiv:2504.19874, Google): dense QR random rotation, no
|
|
24
|
-
groups, no K/V asymmetry, optional QJL residual stage. It anchors the WHY
|
|
25
|
-
(rotate→Gaussian marginal→Lloyd-Max optimal; 4^-b distortion law) but not
|
|
26
|
-
the layout.
|
|
27
|
-
- **vllm-metal** (`vllm-project/vllm-metal`, `vllm_metal/attention/caches/
|
|
28
|
-
turboquant.py` + `kernels_v2/turboquant.metal`): the engineering variant.
|
|
29
|
-
optiq's `runtime/mtp/turboquant.py` config layer is lifted verbatim from it
|
|
30
|
-
(byte-identical `CENTROIDS_3BIT`, matching op signatures in optiq
|
|
31
|
-
`cache_state.py`). **This is our oracle** — "the oracle is whoever ships
|
|
32
|
-
it." Its Python reference functions are pure MLX; we vendor them and
|
|
33
|
-
generate bit-exact goldens with the oracle venv.
|
|
34
|
-
- mlx-vlm's 6.3k-line module is a THIRD design (whole-vector norms, MSE/Prod
|
|
35
|
-
codecs, keys rotated too) — noted, not our target. Its numeric test oracles
|
|
36
|
-
(MSE≈{0.36, 0.117, 0.03} at bits {1,2,3} on unit vectors) are still useful
|
|
37
|
-
sanity anchors for the rotation+Lloyd-Max math.
|
|
38
|
-
- vllm-metal's rendered docs page contradicts its own source (claims keys are
|
|
39
|
-
rotated; the code never rotates keys). Trust the source.
|
|
40
|
-
|
|
41
|
-
## Algorithm (vllm-metal reference semantics, exact)
|
|
42
|
-
|
|
43
|
-
Per token, per kv-head, groups of 32 along head_dim (head_dim ∈ {64,128,256,
|
|
44
|
-
512}, must divide by 32):
|
|
45
|
-
|
|
46
|
-
**Keys — NO rotation, asymmetric affine, per-32-group:**
|
|
47
|
-
- signed (q8_0/int8, bits=8): `max_val=127; scale=(max−min)/(2·max_val);
|
|
48
|
-
zero=round((max+min)/(2·scale)); idx=clip(round(x/scale − zero), −127, 127)`
|
|
49
|
-
stored as int8, one byte per element (no packing at 8 bits).
|
|
50
|
-
- unsigned (q5_0/q4_0/int2…): `max_val=2^bits−1; scale=(max−min)/max_val;
|
|
51
|
-
zero=round(min/scale); idx=clip(round(x/scale − zero), 0, max_val)`, packed.
|
|
52
|
-
- Dequant (both): `x̂=(idx+zero)·scale`. scale/zero fp16, one pair per group.
|
|
53
|
-
- Reference routes intermediates through fp16 (and deliberately drops the
|
|
54
|
-
+1e-8 scale epsilon because it underflows in fp16) — match the Python
|
|
55
|
-
reference's ACTUAL behavior, verified by goldens, not its comments.
|
|
56
|
-
|
|
57
|
-
**Values — FWHT + Lloyd-Max, per-32-group RMS scale:**
|
|
58
|
-
- `y = FWHT(x · signs)` where `signs ∈ {±1}^d` from `mx.random.randint(0,2,
|
|
59
|
-
(d,), key=mx.random.key(42))`, and FWHT normalizes by 1/√d.
|
|
60
|
-
- `scale = sqrt(mean(y²))` per 32-group (RMS, not min/max); `y_n = y/(scale+1e-8)`.
|
|
61
|
-
- `idx = searchsorted(BOUNDARIES, y_n)` — nearest centroid. 3-bit table:
|
|
62
|
-
centroids ±{0.24509, 0.75601, 1.34391, 2.15195}, boundaries ±{0.50055,
|
|
63
|
-
1.04996, 1.74793}, 0. Other bit-widths (2/4/5/8): iterative Lloyd-Max on a
|
|
64
|
-
unit normal — we generate those tables ONCE from the vendored reference and
|
|
65
|
-
hardcode them (parity by construction; no runtime iteration).
|
|
66
|
-
- Pack: flat little-endian bitstream, element i at bits [i·b, i·b+b), values
|
|
67
|
-
may straddle two bytes (3-bit: 8 values → 3 bytes).
|
|
68
|
-
- Dequant: `x̂ = InvFWHT(centroids[idx] · scale · signs⁻¹)` (inverse = apply
|
|
69
|
-
FWHT then multiply signs; Hadamard is an involution up to normalization).
|
|
70
|
-
|
|
71
|
-
**Per-token-per-head bytes (k8v3, d=128):** 128 (K int8) + 8+8 (K scale/zero)
|
|
72
|
-
+ 48 (V packed) + 8 (V scale) = 200 vs 512 bf16 → 2.56×. The centroid table is
|
|
73
|
-
a shared constant, not per-token. This reproduces optiq's `compression_ratio`.
|
|
74
|
-
|
|
75
|
-
**Sign vectors are hardcoded constants per head_dim** (64/128/256/512),
|
|
76
|
-
generated from the reference's key(42) — exactly what vllm-metal does in its
|
|
77
|
-
.metal source. Deterministic across machines and spill/restore.
|
|
78
|
-
|
|
79
|
-
## v1 architecture in mlx-bun
|
|
80
|
-
|
|
81
|
-
Dequantize-on-fetch: `TurboQuantKVCache implements Cache` (does NOT subclass
|
|
82
|
-
KVCache — that keeps it auto-excluded from batching), `updateAndFetch(k,v)`
|
|
83
|
-
quantizes the new tokens into packed storage and returns the dequantized bf16
|
|
84
|
-
active window, so the standard `ops.sdpa` path runs unmodified — the same
|
|
85
|
-
pattern optiq's `runtime/kv/rotating.py` uses for its v1. No generated-file
|
|
86
|
-
changes: a novel cache class fails every `#matches()` guard and falls back to
|
|
87
|
-
the monolith by design. Quantization groups run along head_dim only —
|
|
88
|
-
token-axis slicing stays byte-safe (standing invariant).
|
|
89
|
-
|
|
90
|
-
Files (from the codebase-map seams):
|
|
91
|
-
- `src/mlx/turboquant-ops.ts` — NEW: fwht (bind `mlx_hadamard_transform`,
|
|
92
|
-
confirmed exported by libmlxc), encode/decode keys + values, pack/unpack.
|
|
93
|
-
- `src/mlx/turboquant-tables.ts` — NEW, GENERATED by regen script: sign
|
|
94
|
-
vectors per head_dim + Lloyd-Max centroid/boundary tables per bit-width.
|
|
95
|
-
- `src/model/gemma4-base.ts` — NEW `TurboQuantKVCache` (full-attention only in
|
|
96
|
-
v1; rotating/sliding-window layers stay bf16 — documented limitation).
|
|
97
|
-
- `src/generate.ts` `maybeQuantizeKv()` — the single conversion chokepoint
|
|
98
|
-
(serve serial lane + generate + eval all flow through it); keep the
|
|
99
|
-
`offset===0` skip and `quantizedKvStart` semantics.
|
|
100
|
-
- `src/cli.ts` — `--kv-quant turbo[:k<bits>v<bits>]` (default k8v3).
|
|
101
|
-
- `src/serve/generation-gateway.ts` — explicit solo-only refusal (belt +
|
|
102
|
-
braces on top of the automatic instanceof exclusion).
|
|
103
|
-
- `src/kv-store.ts` — new `CacheKind "turboquant"`, branches in
|
|
104
|
-
snapshotCache/loadKvCache/cloneKvCaches; header carries kBits/vBits.
|
|
105
|
-
- `src/model/fingerprint.ts` — NOT touched, by design symmetry: uniform
|
|
106
|
-
`--kv-quant 4|8` is a CLI-only runtime lever that never feeds
|
|
107
|
-
`configFingerprint()` either (only the per-layer `kv_config.json` scheme
|
|
108
|
-
does); TurboQuant is the same class of lever, so it gets the same
|
|
109
|
-
non-treatment. The SSD-cache compat key (`server.ts`'s `schemeKey`) DOES
|
|
110
|
-
fold in the TurboQuant scheme directly (`turbo-k<bits>v<bits>`), same as it
|
|
111
|
-
already does for uniform bits — that's the actual anti-collision mechanism
|
|
112
|
-
for this class of scheme, not the fingerprint.
|
|
113
|
-
- Docs same-commit: server-config.md, cli.md, features-matrix.md.
|
|
114
|
-
- Tests: `tests/turboquant-ops.test.ts` (golden bit-exactness vs vendored
|
|
115
|
-
reference + model-free math props), `tests/turboquant-cache.test.ts` (cache
|
|
116
|
-
invariants, growth/trim, persistence roundtrip — synthetic arrays, no
|
|
117
|
-
model/golden dependency), `scripts/regen-turboquant-goldens.ts`.
|
|
118
|
-
- `scripts/eval-turboquant-curve.ts` — the Gate 3 quality-vs-bpw curve script:
|
|
119
|
-
bf16 baseline + {k8v8,k8v4,k8v3,k8v2,k4v3,k4v2} sequentially, reusing
|
|
120
|
-
`src/eval/kl.ts`'s `evaluateKlKvArm` (teacher-forced serving-decode KL,
|
|
121
|
-
real `TurboQuantKVCache.fromKVCache` conversion) and
|
|
122
|
-
`src/eval/perplexity.ts`'s `evalPpl` (bf16-forward anchor column).
|
|
123
|
-
Typechecks + `--help`/arg-parsing verified; not yet RUN against a real
|
|
124
|
-
model — that run (and reading the resulting curve against the paper's law)
|
|
125
|
-
is the next stage's job.
|
|
126
|
-
- Vendored reference: `lab/repro/vllm-metal-turboquant/` (their Python file +
|
|
127
|
-
provenance note), driven only by the regen script via the oracle venv.
|
|
128
|
-
|
|
129
|
-
## Gates — ALL PASSED 2026-07-06 (M1 Max 32 GB)
|
|
130
|
-
|
|
131
|
-
Gate 3 measured curve (MiniCPM5-1B, `scripts/eval-turboquant-curve.ts`,
|
|
132
|
-
teacher-forced serving-decode KL vs bf16, 8 prompts × 128 tokens, 32 decode
|
|
133
|
-
steps; affine baselines via the same `evaluateKlKvArm` harness):
|
|
134
|
-
|
|
135
|
-
| scheme | effective KV bits | mean KL vs bf16 |
|
|
136
|
-
|---|---|---|
|
|
137
|
-
| bf16 | 16.00 | 0 (control) |
|
|
138
|
-
| uniform kv8 (affine g64) | 8.50 | 0.00246 |
|
|
139
|
-
| turbo k8v8 | 8.75 | 0.00214 |
|
|
140
|
-
| turbo k8v4 | 6.75 | 0.00936 |
|
|
141
|
-
| **turbo k8v3 (default)** | **6.25** | **0.0325** |
|
|
142
|
-
| turbo k8v2 | 5.75 | 0.175 |
|
|
143
|
-
| uniform kv4 (affine g64) | 4.50 | 0.0516 |
|
|
144
|
-
| turbo k4v3 | 4.25 | 0.0622 |
|
|
145
|
-
| turbo k4v2 | 3.75 | 0.205 |
|
|
146
|
-
|
|
147
|
-
Shape reproduces the paper's law: value bits dominate, ~4^-b decay, cliff at
|
|
148
|
-
v2. Headline: turbo adds operating points between affine kv8/kv4 — the k8v3
|
|
149
|
-
default (2.56× KV compression) beats uniform kv4's KL with room to spare.
|
|
150
|
-
Live smokes: cpm5 + e4b generation coherent under turbo:k8v3 (e4b emits the
|
|
151
|
-
one-time rotating-layers-stay-bf16 warning). The paper's own LongBench
|
|
152
|
-
numbers were NOT rerun (different benchmark harness) — the reproduction is
|
|
153
|
-
shape-level plus the codec-level D_mse≈0.03 anchor, which our 3-bit
|
|
154
|
-
roundtrip test hits.
|
|
155
|
-
|
|
156
|
-
1. **Quantizer parity (bit-exact, the hard gate):** our encode indices,
|
|
157
|
-
scales, zeros, packed bytes, and dequant outputs match the vendored
|
|
158
|
-
vllm-metal Python reference on golden vectors (head_dim 64/128; configs
|
|
159
|
-
k8v3/k4v3/k4v2/k8v4/k2v5/k5v8 — spanning every kBits/vBits value the CLI
|
|
160
|
-
accepts, per the 2026-07-06 integration review). This is an oracle-backed
|
|
161
|
-
scheme at the codec level.
|
|
162
|
-
2. **Math sanity (model-free):** FWHT involution/orthogonality; roundtrip MSE
|
|
163
|
-
at 3-bit on unit-normal data ≈ paper's D_mse≈0.03 band.
|
|
164
|
-
3. **Quality-vs-bpw curve (Phase 13 exit criterion):** teacher-forced KL
|
|
165
|
-
(src/eval/kl.ts) + perplexity vs bf16 KV on MiniCPM5-1B (head_dim 128,
|
|
166
|
-
pure full-attention) across {k8v8, k8v4, k8v3, k8v2, k4v3, k4v2}; curve
|
|
167
|
-
shape must match the paper's law (≈quality-neutral ≥3.5 effective bits,
|
|
168
|
-
marginal degradation at 2.5, cliff below). e4b spot check second. Model
|
|
169
|
-
runs SEQUENTIAL (32 GB box rule).
|
|
170
|
-
4. Whole-repo `tsc --noEmit` = 0; fast suite green; no batching regression
|
|
171
|
-
(turbo requests route serial with a clear reason).
|
|
172
|
-
|
|
173
|
-
## Deferred inverse FWHT (LANDED 2026-07-06, post-v1, Josh-directed)
|
|
174
|
-
|
|
175
|
-
Attention is linear in V, so `InvFWHT(Σᵢ wᵢ·v̂ᵢ) = Σᵢ wᵢ·InvFWHT(v̂ᵢ)`:
|
|
176
|
-
`updateAndFetchDeferredV` returns the V window still in the rotated domain
|
|
177
|
-
and the attention site un-rotates the OUTPUT once per query row
|
|
178
|
-
(`tq.unrotateValues`) — O(q·d log d) per step instead of O(T·d log d).
|
|
179
|
-
Opt-in per attention site via `SharedKv.vRotated` (monolith gemma4.ts —
|
|
180
|
-
KV-shared consumer layers inherit the flag through sharedIn — and
|
|
181
|
-
minicpm5.ts); every other consumer keeps calling `updateAndFetch` (eager)
|
|
182
|
-
and stays correct. Not bit-identical to eager (bf16 rounding in the rotated
|
|
183
|
-
domain before the transform); measured k8v3 KL 0.0338 vs eager 0.0325 —
|
|
184
|
-
same quality. Paired fetch-path A/B on a LOADED M1 Max: never slower,
|
|
185
|
-
~10-20% off fetch cost at 4k ctx, noise-level at 8k (dequant gather
|
|
186
|
-
dominates both paths) — no speed claim until a quiet-machine benchmark.sh
|
|
187
|
-
run; the win is removing the O(T) transform, which matters more once the
|
|
188
|
-
gather itself is fused.
|
|
189
|
-
|
|
190
|
-
## Future: rotation-based WEIGHT quantization (noted 2026-07-06, Josh)
|
|
191
|
-
|
|
192
|
-
The same rotate-then-quantize mechanism applies to weights, and we already
|
|
193
|
-
ship a quantization tool (`convert`/`fuse` verbs) to hang it on — as a
|
|
194
|
-
further optimization of quantization itself, the quantizer leg of the §7.1
|
|
195
|
-
mixed-precision program (allocation × quantizer, same orthogonality as KV):
|
|
196
|
-
|
|
197
|
-
- Rotation smears outlier channels so a low-bit codebook covers the signal
|
|
198
|
-
mass — the QuaRot/SpinQuant family (both cited by the TurboQuant paper).
|
|
199
|
-
- Weights beat KV on one axis: the rotation FOLDS into adjacent weight
|
|
200
|
-
matrices offline (R into one layer, Rᵀ into the next) → zero runtime
|
|
201
|
-
cost, no online transform at all.
|
|
202
|
-
- Weights lose on the other: they're static, so calibration-aware methods
|
|
203
|
-
(GPTQ/AWQ/imatrix, optiq sensitivity maps) are admissible and set a
|
|
204
|
-
higher baseline than any calibration-free scheme — the win to chase is
|
|
205
|
-
rotation COMPOSED WITH calibration/allocation, not instead of it.
|
|
206
|
-
- A Lloyd-Max weight FORMAT needs custom quantized-matmul kernels — the
|
|
207
|
-
26B gather-qmv shelving (dispatch fixed-cost ate the prize) is the
|
|
208
|
-
cautionary precedent. Rotation-folding into mlx's EXISTING affine format
|
|
209
|
-
needs no new kernels and is the cheap first experiment.
|
|
210
|
-
- Activations (W4A4/QuaRot act-quant): more involved (online rotation,
|
|
211
|
-
fused kernels) and mispriced for this hardware — no int4 tensor cores,
|
|
212
|
-
decode is weight-bandwidth-bound. See w4a16-compute-precision-spike.md.
|
|
213
|
-
Not queued.
|
|
214
|
-
|
|
215
|
-
Gate when picked up: perplexity + frozen 6-task eval at equal bpw vs the
|
|
216
|
-
plain affine convert output (the §7.1 gate, eval DB rows).
|
|
217
|
-
|
|
218
|
-
## Non-goals for v1 (recorded so they don't creep)
|
|
219
|
-
|
|
220
|
-
- Fused quantized-SDPA Metal kernel (the remaining fetch cost is the
|
|
221
|
-
unpack+gather; deferred InvFWHT — see above — already landed).
|
|
222
|
-
- Rotating/sliding-window TurboQuant cache; batched TurboQuant; QJL residual
|
|
223
|
-
stage (Q_prod); entropy coding (paper explicitly declined it too).
|
|
224
|
-
- TurboQuant on the speculative lane: `--kv-quant turbo` + `--draft-model`
|
|
225
|
-
keeps the KV scheme — those requests decode serially WITHOUT speculation
|
|
226
|
-
(the spec loop is bf16-KV-only; excluded in the server's spec-eligibility
|
|
227
|
-
gate with a startup warning, 2026-07-07 review fix — turbo was previously
|
|
228
|
-
routed into the spec lane and silently dropped).
|
|
229
|
-
- Head dims beyond {64,128,256,512}: REFUSED AT SERVER START (2026-07-07
|
|
230
|
-
review fix — validation was lazy on the first cache append, so an
|
|
231
|
-
unsupported model 500'd every request mid-prefill; createServer now
|
|
232
|
-
checks the config's full-attention head dim against
|
|
233
|
-
TURBOQUANT_HEAD_DIMS, and the cache-level check stays as the backstop).
|
|
234
|
-
- Speed claims of any kind — v1 dequant-on-fetch is expected slower per-step
|
|
235
|
-
at long context; this ships as a memory/context feature like uniform KV.
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
# Research spike — W4A16 head GEMM (compute precision, not storage)
|
|
2
|
-
|
|
3
|
-
**Status:** proposed (not started) · **Opened:** 2026-06-19 · **Owner:** Josh
|
|
4
|
-
**Surface:** `src/train/flash-cce.ts` (steel + SG kernels) · **Gate:** the existing
|
|
5
|
-
1e-5 CCE parity gate + greedy-prefix logit parity.
|
|
6
|
-
|
|
7
|
-
> One-line thesis (Josh): *we've maxed **storage** quant (4-bit weights), but we
|
|
8
|
-
> dequant into fp32 and run the matmul in fp32 — so the head GEMM is **W4A32**.
|
|
9
|
-
> The untouched lever is **compute** precision: dequant 4-bit → half, matmul in
|
|
10
|
-
> `half` operands with an fp32 accumulator (**W4A16**), gate on parity. Same 4-bit
|
|
11
|
-
> storage, untouched. The only change is the float width we dequant into and
|
|
12
|
-
> multiply in.*
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## TL;DR
|
|
17
|
-
|
|
18
|
-
- The flash-CCE head (forward logit GEMM `E@Wᵀ` and backward phase-2 `coeffᵀ@W`)
|
|
19
|
-
currently runs **W4A32**: 4-bit weights are dequantized into **fp32** threadgroup
|
|
20
|
-
tiles and multiplied with **fp32** simdgroup matrices. Verified in source (below).
|
|
21
|
-
- The 4-bit packing bought the cheap HBM read; the fp32 matmul throws away the
|
|
22
|
-
compute advantage. Apple GPUs run **fp16 FMA at ~2× fp32** on the regular SIMD
|
|
23
|
-
ALUs (no tensor cores). Both head GEMMs are **compute-bound** (see roofline note),
|
|
24
|
-
so half operands are the lever.
|
|
25
|
-
- **Industry-standard for the forward** (MLX `quantized_matmul`, llama.cpp, every
|
|
26
|
-
on-device 4-bit stack do exactly W4A16). Low risk; do it first.
|
|
27
|
-
- **Backward needs the mixed-precision caveat** — fp32 accumulate is non-negotiable
|
|
28
|
-
(already planned), and the **operands** (`coeffᵀ`, `h`) need a dynamic-range probe
|
|
29
|
-
before trusting fp16, specifically the near-zero coeff tails after the skips fire.
|
|
30
|
-
- **M1 Max constraint:** no `bf16` simdgroup_matrix (M2+ only), so **fp16 is the
|
|
31
|
-
only half option** — which makes the range-probe matter more here than on M3.
|
|
32
|
-
- Gate exactly like the existing skip epsilons: **fp32 stays the default-exact
|
|
33
|
-
parity mode**; half is the training default; the 1e-5 gate test runs against fp32.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Current state — verified W4A32
|
|
38
|
-
|
|
39
|
-
The default production path for **both** forward and backward is the **steel**
|
|
40
|
-
kernel (MLX's verbatim `BlockMMA` GEMM, `steel-qmm-header.ts`), selected when
|
|
41
|
-
`H,V,blockV0 % 32 == 0` (`flash-cce.ts:1034`, `:1130`). The `simdgroup_float8x8`
|
|
42
|
-
SG kernels and the scalar/lane kernels are fallbacks for non-32-divisible shapes or
|
|
43
|
-
explicit `MLX_BUN_CCE_*` overrides.
|
|
44
|
-
|
|
45
|
-
Every one of these instantiations is fp32-operand:
|
|
46
|
-
|
|
47
|
-
| path | site | instantiation | operand width |
|
|
48
|
-
|---|---|---|---|
|
|
49
|
-
| steel fwd (default) | `flash-cce.ts:950` | `BlockMMA<float,float,…>` | fp32 |
|
|
50
|
-
| steel bwd phase-1 (default) | `flash-cce.ts:799` | `BlockMMA<float,float,…>` (lmma_t) | fp32 |
|
|
51
|
-
| steel bwd phase-2 (default) | `flash-cce.ts:800` | `BlockMMA<float,float,…>` (dmma_t) | fp32 |
|
|
52
|
-
| steel staging tiles | `:596–598`, loaders `:801` | `threadgroup float` / `BlockLoader<float,…>` | fp32 |
|
|
53
|
-
| SG fwd (fallback) | `:251–254` | `simdgroup_float8x8`, `Csh`/`Esh` = `threadgroup float` | fp32 |
|
|
54
|
-
| SG bwd (fallback) | `:617`, `:684–704` | `simdgroup_float8x8`, `Wsh` = `threadgroup float` | fp32 |
|
|
55
|
-
|
|
56
|
-
The dequant itself (`Csh[…] = sc * q + bi`, `flash-cce.ts:244`) computes into fp32
|
|
57
|
-
and stores fp32. The dh accumulator is already fp32 (`MMATile<float,…>`,
|
|
58
|
-
`flash-cce.ts:828`) — i.e. **the accumulator is already where it should be**; only
|
|
59
|
-
the matmul *operands* are wider than they need to be.
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## The lever — what actually changes
|
|
64
|
-
|
|
65
|
-
W4A16 = **same 4-bit storage, half-width operands, fp32 accumulate.** Concretely:
|
|
66
|
-
|
|
67
|
-
1. **Steel operand type** — the `BlockMMA<float,float,…>` first template param is the
|
|
68
|
-
GEMM input/operand type; flip operand to `half` while keeping the
|
|
69
|
-
accumulator/fragment in `float`. (**Spike task 0: confirm the exact MLX steel
|
|
70
|
-
template param that selects operand vs accumulator width** in
|
|
71
|
-
`steel-qmm-header.ts` before editing — don't assume the param order.)
|
|
72
|
-
2. **Staging tiles** — `Esh`, `Cstg`, `Wsh`, `Csh` go `threadgroup half`; dequant
|
|
73
|
-
arithmetic can stay fp32 then narrow on store, or compute in half.
|
|
74
|
-
3. **Loaders** — `BlockLoader<float,…>` → `BlockLoader<half,…>` to stage half tiles.
|
|
75
|
-
4. **SG fallback** — `simdgroup_float8x8` → `simdgroup_half8x8` for the operands,
|
|
76
|
-
keep an `simdgroup_float8x8` accumulator (Apple supports the mixed `half×half→float`
|
|
77
|
-
`simdgroup_multiply_accumulate`).
|
|
78
|
-
|
|
79
|
-
Everything reduction-shaped (the online-softmax `m`/`d` recurrence, the dh accum,
|
|
80
|
-
logsumexp) **stays fp32**.
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## First thoughts (mine) — what to add to Josh's analysis
|
|
85
|
-
|
|
86
|
-
The analysis is right and the change is well-targeted. Five additions, each grounded
|
|
87
|
-
in the current source:
|
|
88
|
-
|
|
89
|
-
**1. Aim at the steel kernel, not the SG snippet.** Josh's note led with the SG path
|
|
90
|
-
(`simdgroup_float8x8`, `Csh`). That path is a *fallback*. The lever that moves the
|
|
91
|
-
measured 180 ms fwd / 754 ms bwd (e4b) numbers is the **steel `BlockMMA<float,float>`**
|
|
92
|
-
instantiations (`:950`, `:799`, `:800`) and their `BlockLoader<float>`/staging tiles.
|
|
93
|
-
Do the SG path too for completeness, but the steel path is where the production time is.
|
|
94
|
-
|
|
95
|
-
**2. The 2× is an upper bound gated by the FMA fraction — get the roofline split
|
|
96
|
-
first.** The whole flash-CCE design is `[M,V]`-free and amortizes dequant across
|
|
97
|
-
`BLOCK_B` tokens specifically because the **dequant ALU** was "the dominant cost in
|
|
98
|
-
v1" (`flash-cce.ts:59`). The runtime splits into (a) nibble-unpack + `sc·q+bi`
|
|
99
|
-
dequant and (b) the FMA matmul. **W4A16 only speeds up (b).** The kernel is
|
|
100
|
-
unambiguously compute-bound, not BW-bound — **confirmed live** (see the measured box
|
|
101
|
-
below), and Josh flagged it from `mactop` before this doc existed. *But* the win
|
|
102
|
-
ceiling is the FMA share of that ALU time. The dequant-amortization work was done
|
|
103
|
-
precisely to shrink (a)'s share, which *should* leave (b) dominant and favorable — but
|
|
104
|
-
**measure the (a)/(b) split before predicting 2×.** The live numbers prove the
|
|
105
|
-
*whole kernel* is ALU-bound; they do **not** resolve the intra-kernel (a)/(b) split,
|
|
106
|
-
which is what actually bounds the reclaim. If the kernel is still dequant-ALU-bound,
|
|
107
|
-
half operands move it less.
|
|
108
|
-
|
|
109
|
-
> **Live roofline — measured (M1 Max 32 GB, MiniCPM5-1B ORPO, `--no-segment`, seq 4096):**
|
|
110
|
-
> GPU **100% @ 1296 MHz, 81 °C, Nominal** (sustained, not throttling) · memory
|
|
111
|
-
> **BW 129.2 GB/s ≈ ⅓ of the M1 Max's ~400 GB/s ceiling** (bus two-thirds idle) ·
|
|
112
|
-
> mem **17.37 / 32 GB (54%)**, swap 0 · CPU ~5%, ANE 0%. The training `bun` proc is
|
|
113
|
-
> 92.6% GPU. **GPU pegged + memory bus mostly idle = ALU-bound.** This is the regime
|
|
114
|
-
> where W4A16 pays; if it were BW-bound (BW near 400, GPU spiky) the spike would be
|
|
115
|
-
> moot. The 4-bit storage already did its job — *that's why BW is low* — and the GPU
|
|
116
|
-
> is now spending its cycles on the fp32 FMAs.
|
|
117
|
-
|
|
118
|
-
**3. Threadgroup memory is a free secondary win — possibly a compounding one.** The
|
|
119
|
-
staging tiles (`Esh`/`Cstg`/`Wsh`/`Csh`) are the kernel's threadgroup-memory pressure,
|
|
120
|
-
and tile sizing is *already* occupancy-constrained — see the note at `flash-cce.ts:71`
|
|
121
|
-
("the 8KB `Csh` tile measured SLOWER"). Half-width staging **halves that footprint**,
|
|
122
|
-
which can either raise occupancy or admit larger tiles. So W4A16 may buy more than the
|
|
123
|
-
raw 2× FMA: it could relieve the exact constraint that capped the current tiling.
|
|
124
|
-
Worth re-sweeping `BLOCK_B`/tile dims *after* the precision change, not just measuring
|
|
125
|
-
the drop-in.
|
|
126
|
-
|
|
127
|
-
**4. SDPA in the segmented forward is probably already half — don't chase it.** Josh's
|
|
128
|
-
aside ("if your SDPA tiles are also fp32, same logic"). The segmented forward uses
|
|
129
|
-
`ops.sdpa` — MLX's own fused flash kernel ([[opssdpa-dk-vjp-bug]]) — which runs in the
|
|
130
|
-
model's dtype (bf16), **not** our fp32 tiles. So that lever is likely already pulled by
|
|
131
|
-
delegating to MLX. One-line confirm, then drop it; the head GEMM is the real target.
|
|
132
|
-
|
|
133
|
-
**5. Free instrumentation hooks already exist for the backward range-probe.** The
|
|
134
|
-
backward already computes `cmax = simd_max(coeff)` for the FILTER_EPS skip
|
|
135
|
-
(`flash-cce.ts:682`). That same reduction is the natural hook to log the coeff dynamic
|
|
136
|
-
range (min nonzero |coeff|) across a real run *before* committing the operand to fp16 —
|
|
137
|
-
the underflow-to-zero case Josh flagged. Pair it with a max-abs probe on `h`: at e4b's
|
|
138
|
-
`scale=1.0` peaked attention the residual stream can carry outliers
|
|
139
|
-
([[e4b-forward-length-sensitivity]], [[siglip-vision-parity-cross-build]]), and with no
|
|
140
|
-
bf16 on M1 Max we can't lean on a wider exponent to eat them.
|
|
141
|
-
|
|
142
|
-
---
|
|
143
|
-
|
|
144
|
-
## Risk analysis (preserving the forward/backward split)
|
|
145
|
-
|
|
146
|
-
**Forward — low risk, boring industry default.** Logits are well-scaled; the
|
|
147
|
-
online-softmax max-subtraction bounds the `exp` args. W4A16 here is what the dense
|
|
148
|
-
path already assumes. Validate against the 1e-5 gate (fp16 operands won't hold 1e-5 —
|
|
149
|
-
that's expected; the **fp32 path stays the exact-parity gate**, half is graded by
|
|
150
|
-
greedy-prefix logit agreement, same as the vision tier-a bar).
|
|
151
|
-
|
|
152
|
-
**Backward — fp16 matmul is mainstream, but as *mixed precision*, with eyes on
|
|
153
|
-
operand range.** What makes the forward safe (well-scaled, max-subtracted) is **not**
|
|
154
|
-
automatically true here:
|
|
155
|
-
- `coeff_v = g·(onehot − softmax)·sech²` — after the skips fire, the survivors are the
|
|
156
|
-
**near-zero tails**. Small magnitudes are exactly where fp16's ~3-digit mantissa and
|
|
157
|
-
narrow range (subnormals < ~6e-5) bite. **`coeffᵀ` as an fp16 operand is the highest
|
|
158
|
-
risk** — tail coeffs underflowing to zero silently drop gradient contribution. Probe
|
|
159
|
-
the range first (task 5 above).
|
|
160
|
-
- `h` (activations) as fp16 operand — residual outliers; the classic bf16-beats-fp16
|
|
161
|
-
case, but bf16 isn't available on M1 Max. Range-check before trusting.
|
|
162
|
-
- **fp32 accumulate is non-negotiable** (already planned; `MMATile<float>` already is).
|
|
163
|
-
- **Validate grads against autograd, not a hand-derived backward** ([[opssdpa-dk-vjp-bug]]).
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## Spike plan
|
|
168
|
-
|
|
169
|
-
Sequenced so each step is independently measurable and revertible (Josh: *"Don't flip
|
|
170
|
-
both at once — you'll learn more, and if parity drifts you'll know which GEMM did it."*).
|
|
171
|
-
|
|
172
|
-
- [ ] **0. Confirm the steel template semantics.** In `steel-qmm-header.ts`, identify
|
|
173
|
-
which `BlockMMA`/`BlockLoader` template params are operand vs accumulator width.
|
|
174
|
-
Exit: a one-line mapping, no code change.
|
|
175
|
-
- [x] **1a. Whole-kernel roofline — DONE (live).** GPU 100% / BW 129 GB/s (~⅓ of 400)
|
|
176
|
-
on M1 Max confirms the kernel is ALU-bound, not BW-bound (see the measured box above).
|
|
177
|
-
The spike is worth chasing.
|
|
178
|
-
- [ ] **1b. Intra-kernel split (still open).** Profile the steel fwd (180 ms) and bwd
|
|
179
|
-
(754 ms, e4b) into dequant-ALU vs FMA fractions — 1a says the GPU is the wall, this
|
|
180
|
-
says *which part* of the GPU work. Exit: a number that bounds the expected win. *If
|
|
181
|
-
FMA < ~40% of either kernel, reset expectations before coding.*
|
|
182
|
-
- [ ] **2. Add the precision gate.** New codegen `#define` (e.g. `CCE_A_HALF`) +
|
|
183
|
-
env flag (e.g. `MLX_BUN_CCE_A16`), mirroring `CCE_BWD_FILTER_EPS`/`CCE_BWD_BLOCK_EPS`
|
|
184
|
-
(`flash-cce.ts:732`,`:739`). Default: fp32 (exact) for the parity suite; half is the
|
|
185
|
-
training default. Per [[three-level-fidelity-tree-model]] the exact path must stay
|
|
186
|
-
selectable.
|
|
187
|
-
- [ ] **3. Forward → half operands.** Steel fwd `BlockMMA`/loader/staging to half.
|
|
188
|
-
Validate: 1e-5 gate (fp32 path) + greedy-prefix logit parity (half path) + measure
|
|
189
|
-
the fwd GEMM delta. Land as its own change.
|
|
190
|
-
- [ ] **4. Backward range probe.** Instrument coeff (via the `simd_max` hook) and `h`
|
|
191
|
-
dynamic range across a real MiniCPM5/e4b ORPO step. Exit: min-nonzero-coeff and
|
|
192
|
-
max-|h| numbers + a go/no-go on fp16 operands.
|
|
193
|
-
- [ ] **5. Backward → half operands** (only if 4 says go). `coeffᵀ`/`h`/`W` operands
|
|
194
|
-
half, dh accumulator stays fp32. Validate grads **vs autograd** + measure bwd delta.
|
|
195
|
-
- [ ] **6. Re-sweep tiling.** With half-width staging, re-check `BLOCK_B`/tile dims and
|
|
196
|
-
occupancy (first-thought #3) — the precision win may unlock a tiling win.
|
|
197
|
-
|
|
198
|
-
**Exit criteria for the spike:** a measured fwd/bwd speedup on e4b (V=262144) and
|
|
199
|
-
MiniCPM5 (V=130560) on the bench machine (M4 Pro 24 GB; numbers verified against
|
|
200
|
-
`~/.cache/mlx-bun/evals.sqlite`, not docs — [[verify-benchmarks-against-evaldb-not-docs]]),
|
|
201
|
-
with the fp32 exact path still passing the 1e-5 gate and the half training path inside
|
|
202
|
-
the greedy-prefix parity bar. Either it lands as the training default behind the gate,
|
|
203
|
-
or the roofline/range data explains why it didn't pay and the spike closes with that.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Open questions
|
|
208
|
-
|
|
209
|
-
- Steel `BlockMMA` mixed operand/accum: does MLX's steel already support
|
|
210
|
-
`half`-operand / `float`-accum, or does it need a local template tweak? (task 0)
|
|
211
|
-
- Is the dequant cheaper to do **in half** (fewer ALU bits) or **in fp32 then narrow**
|
|
212
|
-
(preserves the scale/bias precision)? A/B inside task 3.
|
|
213
|
-
- Does the half staging change the `+4-float` padding trick (`flash-cce.ts:197`, the
|
|
214
|
-
BK_padded bank-conflict avoidance)? Half-width may re-introduce or shift bank
|
|
215
|
-
conflicts — re-derive the pad.
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## References
|
|
220
|
-
|
|
221
|
-
**Code:** `src/train/flash-cce.ts` — steel fwd `:937–1028`, steel bwd `:763–935`, SG
|
|
222
|
-
fwd `:174–270`, SG bwd `:561–726`, gates `:732`/`:739`/`:1034`/`:1130`; staging tiles
|
|
223
|
-
`:596–598`; dequant `:244`; coeff `simd_max` hook `:682`; dh fp32 accum `:828`.
|
|
224
|
-
`src/train/steel-qmm-header.ts` (the verbatim MLX BlockMMA). `src/mlx/metal-kernel.ts`
|
|
225
|
-
(kernel infra).
|
|
226
|
-
|
|
227
|
-
**Cross-links:** [[flash-cce-metal-kernel-prototype]] · [[three-level-fidelity-tree-model]]
|
|
228
|
-
· [[opssdpa-dk-vjp-bug]] · [[e4b-forward-length-sensitivity]] ·
|
|
229
|
-
[[verify-benchmarks-against-evaldb-not-docs]] · `docs/investigations/steel-flash-cce-handoff.md`.
|
|
230
|
-
|
|
231
|
-
**Sibling deferred lever** (queued together, post-run): `docs/design/orpo-future-enhancements.md`
|
|
232
|
-
→ "Deferred levers" (expose `--grad-accum`).
|