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.
Files changed (427) hide show
  1. package/README.md +71 -578
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/README.md +91 -0
  4. package/docs/{design → archive}/hlg-sampling.md +3 -3
  5. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  6. package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
  7. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  8. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  9. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  10. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  11. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  12. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  13. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  14. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  15. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  16. package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
  17. package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
  18. package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
  19. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  20. package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
  21. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  22. package/docs/design/batching.md +569 -0
  23. package/docs/design/decode-speed-program.md +3178 -169
  24. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  25. package/docs/design/generic-model-support.md +579 -334
  26. package/docs/design/kv-cache.md +680 -0
  27. package/docs/design/orpo-training.md +673 -1239
  28. package/docs/design/speculative-decoding.md +1627 -0
  29. package/docs/design/turboquant.md +2102 -0
  30. package/docs/design/unified-engine-frontier-plan.md +1831 -727
  31. package/docs/design/web-chat-redesign.md +666 -1083
  32. package/docs/planning/PRODUCT_ROADMAP.md +34 -1
  33. package/docs/planning/release-notes-v0.3.0.md +35 -0
  34. package/docs/planning/video-series.md +421 -0
  35. package/docs/reference/benchmarks.md +1162 -0
  36. package/docs/reference/cli.md +395 -149
  37. package/docs/reference/distribution.md +321 -181
  38. package/docs/reference/environment.md +348 -0
  39. package/docs/reference/glossary.md +39 -0
  40. package/docs/reference/library-api.md +580 -142
  41. package/docs/reference/memory.md +227 -64
  42. package/docs/reference/models.md +137 -6
  43. package/docs/reference/server-api.md +938 -422
  44. package/docs/reference/server-config.md +652 -320
  45. package/docs/reference/training.md +393 -254
  46. package/docs/reference/troubleshooting.md +166 -0
  47. package/package.json +10 -5
  48. package/src/admission-plan.ts +18 -0
  49. package/src/anthropic.ts +92 -3
  50. package/src/audio/decode.ts +2 -2
  51. package/src/audio/features.ts +2 -2
  52. package/src/backends/mlx/autoregressive.ts +108 -0
  53. package/src/backends/mlx/batch-group.ts +1646 -0
  54. package/src/backends/mlx/diffusion.ts +39 -0
  55. package/src/backends/mlx/draft-target.ts +47 -0
  56. package/src/backends/mlx/evaluation.ts +105 -0
  57. package/src/backends/mlx/fill-append.ts +45 -0
  58. package/src/backends/mlx/gateway-binding.ts +71 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/memory-client.ts +189 -0
  61. package/src/backends/mlx/memory-guard.ts +40 -0
  62. package/src/backends/mlx/methods.ts +90 -0
  63. package/src/backends/mlx/model-prompt.ts +164 -0
  64. package/src/backends/mlx/model-serving.ts +79 -0
  65. package/src/backends/mlx/prefill.ts +33 -0
  66. package/src/backends/mlx/request-policy.ts +20 -0
  67. package/src/backends/mlx/rollback.ts +51 -0
  68. package/src/backends/mlx/serial-executor.ts +273 -0
  69. package/src/backends/mlx/speculative.ts +114 -0
  70. package/src/backends/mlx/state-views.ts +26 -0
  71. package/src/backends/mlx/text-engine.ts +73 -0
  72. package/src/cli.ts +189 -61
  73. package/src/client.ts +66 -0
  74. package/src/config.ts +21 -4
  75. package/src/contracts/completion.ts +16 -0
  76. package/src/contracts/execution.ts +49 -0
  77. package/src/contracts/generation.ts +103 -0
  78. package/src/contracts/host.ts +7 -0
  79. package/src/contracts/jobs.ts +66 -0
  80. package/src/contracts/pi-provider.ts +30 -0
  81. package/src/contracts/pi.ts +259 -0
  82. package/src/contracts/resources.ts +18 -0
  83. package/src/contracts/scheduling.ts +27 -0
  84. package/src/contracts/tsconfig.json +14 -0
  85. package/src/diffusion/diffusion-generate.ts +218 -153
  86. package/src/embed.ts +1 -1
  87. package/src/engine/admission.ts +59 -0
  88. package/src/engine/cancellation.ts +38 -0
  89. package/src/engine/engine.ts +56 -0
  90. package/src/engine/execution-coordinator.ts +70 -0
  91. package/src/engine/execution-plan.ts +51 -0
  92. package/src/engine/resources.ts +42 -0
  93. package/src/engine/scheduler.ts +67 -0
  94. package/src/engine/session.ts +247 -0
  95. package/src/eval/README.md +44 -1
  96. package/src/eval/kl.ts +263 -23
  97. package/src/eval/reference-logits.ts +207 -0
  98. package/src/eval/runner.ts +10 -79
  99. package/src/eval/tasks/bfcl.ts +2 -1
  100. package/src/eval/tasks/gsm8k.ts +2 -1
  101. package/src/eval/tasks/hashhop.ts +2 -1
  102. package/src/eval/tasks/humaneval.ts +5 -4
  103. package/src/eval/tasks/ifeval.ts +2 -1
  104. package/src/eval/tasks/mmlu.ts +2 -1
  105. package/src/expert-io.ts +3 -1
  106. package/src/expert-offload.ts +3 -1
  107. package/src/fill/echo-index.ts +188 -0
  108. package/src/fill/fill-session.ts +452 -0
  109. package/src/fill/proposal.ts +68 -0
  110. package/src/fill/schema-rows.ts +506 -0
  111. package/src/fill/tool-boundary.ts +103 -0
  112. package/src/fit.ts +24 -43
  113. package/src/generate.ts +740 -337
  114. package/src/grammar.ts +14 -8
  115. package/src/harness-pi.ts +15 -34
  116. package/src/hub-rest.ts +4 -4
  117. package/src/index.ts +27 -0
  118. package/src/inference/denoising.ts +17 -0
  119. package/src/inference/graph.ts +33 -0
  120. package/src/inference/prefill.ts +39 -0
  121. package/src/inference/rollback.ts +7 -0
  122. package/src/jobs/db.ts +4 -0
  123. package/src/jobs/index.ts +2 -0
  124. package/src/jobs/job-entry.ts +15 -14
  125. package/src/jobs/runner.ts +98 -13
  126. package/src/jobs/task-client.ts +19 -0
  127. package/src/jobs/types.ts +2 -58
  128. package/src/kv-scheme.ts +199 -0
  129. package/src/kv-store.ts +459 -234
  130. package/src/lab/README.md +18 -0
  131. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  132. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  133. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
  134. package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
  135. package/src/library.ts +40 -0
  136. package/src/lora.ts +18 -0
  137. package/src/media-fetch.ts +20 -4
  138. package/src/memory/article.ts +1 -1
  139. package/src/memory/chunk.ts +1 -1
  140. package/src/memory/model.ts +32 -170
  141. package/src/memory/prompts.ts +1 -1
  142. package/src/memory/rest.ts +1 -1
  143. package/src/memory/schedule.ts +1 -1
  144. package/src/memory/stages.ts +4 -1
  145. package/src/memory/vault.ts +3 -4
  146. package/src/mlx/array.ts +9 -10
  147. package/src/mlx/compile.ts +12 -2
  148. package/src/mlx/ffi.ts +66 -22
  149. package/src/mlx/materialize.ts +23 -0
  150. package/src/mlx/metal-kernel.ts +10 -11
  151. package/src/mlx/ops.ts +64 -19
  152. package/src/mlx/quantized-rows.ts +36 -0
  153. package/src/mlx/token-bitmask.ts +52 -0
  154. package/src/mlx/turboquant-kv-decode.ts +82 -0
  155. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  156. package/src/mlx/turboquant-ops.ts +33 -3
  157. package/src/mlx/turboquant-tables.ts +2 -2
  158. package/src/model/batched-mask.ts +9 -3
  159. package/src/model/batched-quant.ts +2 -2
  160. package/src/model/batched-rotating-quant.ts +45 -99
  161. package/src/model/batched-rotating-state.ts +73 -0
  162. package/src/model/batched-rotating.ts +57 -106
  163. package/src/model/batched-row-storage.ts +127 -0
  164. package/src/model/compiled-decode.ts +4 -3
  165. package/src/model/diffusion-gemma.ts +8 -8
  166. package/src/model/factory.ts +87 -49
  167. package/src/model/fingerprint.ts +1 -1
  168. package/src/model/flash-attention.ts +3 -3
  169. package/src/model/gemma4-base.ts +187 -17
  170. package/src/model/gemma4.ts +6 -6
  171. package/src/model/generated/gemma4-12b.ts +52 -148
  172. package/src/model/generated/gemma4-26b.ts +34 -94
  173. package/src/model/generated/gemma4-e4b.ts +28 -76
  174. package/src/model/glm52-cache.ts +19 -9
  175. package/src/model/glm52-dsa.ts +13 -9
  176. package/src/model/glm52-memory.ts +28 -1
  177. package/src/model/implementation.ts +69 -0
  178. package/src/model/minicpm5.ts +7 -8
  179. package/src/model/profile.ts +443 -0
  180. package/src/model/qwen-append.ts +12 -0
  181. package/src/model/qwen-conv.ts +52 -0
  182. package/src/model/qwen3-delta.ts +98 -2
  183. package/src/model/qwen3-mrope.ts +252 -0
  184. package/src/model/qwen3_5-checkpoint.ts +164 -0
  185. package/src/model/qwen3_5.ts +336 -60
  186. package/src/model/support.ts +1 -1
  187. package/src/model/trellis-balanced-scatter.ts +51 -0
  188. package/src/model/trellis-linear.ts +672 -0
  189. package/src/model/trellis-shared-m.ts +151 -0
  190. package/src/model/trellis-shared-scatter.ts +144 -0
  191. package/src/model/trellis-splitk-prefill.ts +158 -0
  192. package/src/model/trellis-tiled-prefill.ts +136 -0
  193. package/src/model/trellis-vector-expand.ts +62 -0
  194. package/src/model/trellis-wide-prefill.ts +94 -0
  195. package/src/model/universal/dense.ts +1 -1
  196. package/src/model/universal/modules.ts +8 -1
  197. package/src/native/frame_extract.swift +140 -0
  198. package/src/native-pack.ts +15 -7
  199. package/src/pi-provider.ts +6 -64
  200. package/src/pi-web.ts +14 -320
  201. package/src/prompt-cache.ts +97 -54
  202. package/src/quantize/allocator.ts +1 -1
  203. package/src/quantize/atomic-output.ts +38 -0
  204. package/src/quantize/calibration.ts +2 -1
  205. package/src/quantize/config-writer.ts +16 -3
  206. package/src/quantize/index.ts +28 -1
  207. package/src/quantize/job.ts +11 -0
  208. package/src/quantize/quantizer.ts +265 -100
  209. package/src/quantize/rotate.ts +603 -0
  210. package/src/quantize/safetensors-writer.ts +79 -1
  211. package/src/quantize/sensitivity.ts +41 -59
  212. package/src/quantize/trellis.ts +586 -0
  213. package/src/quantize/weight-transform.ts +292 -0
  214. package/src/responses.ts +130 -3
  215. package/src/runtime-config.ts +81 -0
  216. package/src/sampler.ts +276 -4
  217. package/src/serve/admin-routes.ts +184 -0
  218. package/src/serve/aux-routes.ts +132 -0
  219. package/src/serve/batch-scheduler.ts +8 -1558
  220. package/src/serve/chat-request.ts +391 -0
  221. package/src/serve/chat-stage.ts +195 -0
  222. package/src/serve/checkpoint-identity.ts +64 -0
  223. package/src/serve/completion-executor.ts +354 -0
  224. package/src/serve/completion-sink.ts +157 -0
  225. package/src/serve/discovery-routes.ts +204 -0
  226. package/src/serve/generation-gateway.ts +211 -243
  227. package/src/serve/http.ts +159 -0
  228. package/src/serve/inference-request.ts +79 -0
  229. package/src/serve/isolate.ts +297 -105
  230. package/src/serve/kv-budget.ts +14 -0
  231. package/src/serve/lab-routes.ts +341 -0
  232. package/src/serve/lane-registry.ts +2 -1
  233. package/src/serve/model-admin-routes.ts +155 -0
  234. package/src/serve/model-binding.ts +43 -0
  235. package/src/serve/model-host.ts +512 -0
  236. package/src/serve/openai-wire.ts +103 -0
  237. package/src/serve/parent-application.ts +56 -0
  238. package/src/serve/pipeline.ts +33 -0
  239. package/src/serve/preparation.ts +33 -0
  240. package/src/serve/prompt-response-trace.ts +147 -0
  241. package/src/serve/request-plan.ts +162 -0
  242. package/src/serve/request-prep.ts +346 -0
  243. package/src/serve/response-lease.ts +24 -0
  244. package/src/serve/responses-client.ts +69 -0
  245. package/src/serve/session-completion-engine.ts +110 -0
  246. package/src/serve/session-search.ts +1 -1
  247. package/src/serve/static-routes.ts +101 -0
  248. package/src/serve/text-completion-stage.ts +104 -0
  249. package/src/serve/token-streams.ts +519 -0
  250. package/src/server.ts +523 -3551
  251. package/src/spec/assistant-source.ts +10 -44
  252. package/src/spec/deepspec-source.ts +6 -6
  253. package/src/spec/dflash-source.ts +9 -8
  254. package/src/spec/dspark/ab-stats.ts +3 -3
  255. package/src/spec/dspark/calibration.ts +2 -2
  256. package/src/spec/dspark/deepspec-module.ts +2 -2
  257. package/src/spec/dspark/generate-dflash.ts +2 -2
  258. package/src/spec/dspark/generate.ts +2 -2
  259. package/src/spec/dspark/loader.ts +1 -1
  260. package/src/spec/dspark/module-dflash.ts +5 -4
  261. package/src/spec/dspark/module.ts +3 -3
  262. package/src/spec/dspark/quantize-drafter.ts +1 -1
  263. package/src/spec/generate.ts +1 -1
  264. package/src/spec/glm52-mtp-source.ts +9 -1
  265. package/src/spec/ngram-source.ts +1 -1
  266. package/src/spec/prefix-state.ts +45 -0
  267. package/src/spec/qwen-mtp-source.ts +528 -0
  268. package/src/spec/serve-loop.ts +179 -213
  269. package/src/spec/source.ts +42 -10
  270. package/src/spec/two-model.ts +1 -1
  271. package/src/ssd-cache.ts +95 -24
  272. package/src/ssd-durability.ts +207 -0
  273. package/src/tool-call.ts +51 -14
  274. package/src/train/flash-cce.ts +14 -13
  275. package/src/train/forward.ts +38 -1
  276. package/src/train/loss.ts +3 -2
  277. package/src/train/prefix-shared.ts +5 -1
  278. package/src/train/segmented.ts +9 -6
  279. package/src/train/trainer.ts +9 -8
  280. package/src/vision/preprocess.ts +1 -1
  281. package/src/vision/prompt.ts +48 -2
  282. package/src/vision/qwen3vl-preprocess.ts +409 -0
  283. package/src/vision/qwen3vl-prompt.ts +196 -0
  284. package/src/vision/qwen3vl-tower.ts +555 -0
  285. package/src/vision/video-frames.ts +148 -0
  286. package/src/web/app.html +1 -1
  287. package/src/web/app.js +15 -6
  288. package/src/web/src/adapters-panel.ts +3 -3
  289. package/src/web/src/assistant.ts +2 -36
  290. package/src/web/src/chat.ts +16 -9
  291. package/src/web/src/composer.ts +4 -4
  292. package/src/web/src/hub.ts +1 -1
  293. package/src/web/src/markdown.ts +0 -0
  294. package/src/web/src/memory-panel.ts +1 -1
  295. package/src/web/src/model-picker.ts +1 -1
  296. package/src/web/src/palette.ts +1 -1
  297. package/src/web/src/protocol.ts +3 -39
  298. package/src/web/src/sessions.ts +1 -1
  299. package/src/web/src/ui-catalog.ts +4 -18
  300. package/src/web-assets.ts +47 -0
  301. package/src/weights.ts +134 -33
  302. package/docs/archive/mlx-bun-lab-report.html +0 -275
  303. package/docs/archive/wwdc-mlx-bun.html +0 -848
  304. package/docs/design/adapters-end-to-end.md +0 -205
  305. package/docs/design/batching-perf-path.md +0 -255
  306. package/docs/design/batching-v2-plan.md +0 -529
  307. package/docs/design/bucketing-stage.md +0 -197
  308. package/docs/design/compat-cli-surface-design.md +0 -230
  309. package/docs/design/docs-reorg-plan.md +0 -165
  310. package/docs/design/dspark-serving-program.md +0 -371
  311. package/docs/design/dspark-speculative-decoding.md +0 -268
  312. package/docs/design/grammar-spec-batching-integration.md +0 -301
  313. package/docs/design/memory-inference-path.md +0 -422
  314. package/docs/design/memory-synthesis.md +0 -287
  315. package/docs/design/memory-system.md +0 -237
  316. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  317. package/docs/design/omlx-adoption-map.md +0 -98
  318. package/docs/design/orpo-dynamic-lambda.md +0 -220
  319. package/docs/design/orpo-future-enhancements.md +0 -340
  320. package/docs/design/paged-kv-cache.md +0 -214
  321. package/docs/design/parallel-slots.md +0 -567
  322. package/docs/design/parity-tier-dag.md +0 -161
  323. package/docs/design/repo-cleanup-plan.md +0 -189
  324. package/docs/design/runtime-isolation.md +0 -263
  325. package/docs/design/segmented-backward-training.md +0 -543
  326. package/docs/design/spec-decode-larger-targets.md +0 -229
  327. package/docs/design/ssd-kv-cold-tier.md +0 -288
  328. package/docs/design/structured-output.md +0 -484
  329. package/docs/design/tauri-desktop-app.md +0 -127
  330. package/docs/design/the-dreaming-master-plan.md +0 -445
  331. package/docs/design/turboquant-kv.md +0 -235
  332. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  333. package/docs/design/web-chat-beat-matrix.md +0 -315
  334. package/docs/design/write-pipeline-entity.md +0 -468
  335. package/docs/investigations/curve-runs/bisector-route.json +0 -98
  336. package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
  337. package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
  338. package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
  339. package/docs/investigations/hlg-ab.html +0 -34
  340. package/docs/investigations/hlg-explorer.html +0 -238
  341. package/docs/investigations/hlg-figs/cliff.svg +0 -1
  342. package/docs/investigations/hlg-figs/cross.svg +0 -1
  343. package/docs/investigations/hlg-figs/edges.svg +0 -1
  344. package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
  345. package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
  346. package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
  347. package/docs/investigations/hlg-figs/terrain.svg +0 -1
  348. package/docs/investigations/hlg-report.html +0 -262
  349. package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
  350. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  351. package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
  352. package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
  353. package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
  354. package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
  355. package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
  356. package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
  357. package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
  358. package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
  359. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  360. package/docs/investigations/hlg-runs/hlg-map.json +0 -383
  361. package/docs/investigations/hlg-runs/run0-original.log +0 -159
  362. package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
  363. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  364. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  365. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  366. package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  367. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  368. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  369. package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  370. package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
  371. package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
  372. package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
  373. package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
  374. package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
  375. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  376. package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
  377. package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
  378. package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
  379. package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
  380. package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
  381. package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  382. package/docs/investigations/hlg-runs/runN-verify.log +0 -116
  383. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  384. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  385. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  386. package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  387. package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  388. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  389. package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
  390. package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  391. package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
  392. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  393. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  394. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  395. package/docs/planning/IDEAS.md +0 -69
  396. package/docs/reference/embedding.md +0 -197
  397. package/docs/reference/features-matrix.md +0 -100
  398. package/docs/reference/orpo-quickstart.md +0 -135
  399. package/src/flags.ts +0 -13
  400. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  401. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  402. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  403. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  404. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  405. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  406. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  407. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  408. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  409. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  410. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  411. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  412. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  413. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  414. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  415. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  416. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  417. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  418. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  419. /package/docs/{planning → archive/planning}/journal.md +0 -0
  420. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  421. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  422. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  423. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  424. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  425. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
  426. /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
  427. /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`).