11# coldpath
22
3- ** The most popular way to run an LLM on an Arm laptop ships with its matrix hardware switched off. I
4- found it with a tool that had to be built, fixed it for ~ 6x, and made the fix impossible to regress.**
3+ ** Popular LLM runtimes ship on Arm with the chip's matrix hardware switched off. On Azure Cobalt 100
4+ (Neoverse N2, a cloud Arm CPU) that costs 5.75x on prompt-processing throughput: 5.75x fewer tokens per
5+ core-hour, the same 5.75x on the cloud bill. I built the tool that finds it in any binary, fixed the most
6+ popular offender in one line upstream, and gated it so a cold build can't reach your Arm cloud fleet.**
57
6- ` coldpath ` disassembles any AArch64 binary and proves whether it can actually execute the chip's
7- matrix and dot-product instructions (SME/SME2, i8mm, bf16, dotprod). It needs no Arm hardware and no
8- profiler; it runs on the x86 laptop you already have, and it runs as a CI gate.
8+ ` coldpath ` disassembles any AArch64 binary and proves whether it * contains, and can dispatch,* the chip's
9+ matrix and dot-product instructions (SME/SME2, i8mm, bf16, dotprod). Absence is dispositive: zero ` smmla `
10+ means the binary cannot run an i8mm matmul on any core. It needs no Arm hardware and no profiler; it runs
11+ on the x86 laptop you already have, and as a CI gate that stops a cold build reaching production.
912
1013---
1114
@@ -22,25 +25,26 @@ lib/ollama/ggml-cpu.dll
2225 -- dotprod (sdot) 0
2326```
2427
25- Ollama's official Windows-on-Arm build (v0.31.2) executes ** zero** matrix and ** zero** dot-product
26- instructions. Every Snapdragon X laptop running it does LLM matrix multiplication in scalar/NEON only.
28+ That is Ollama's official Windows-on-Arm build (v0.31.2): ** zero** matrix, ** zero** dot-product
29+ instructions, every matmul in scalar/NEON. It is not a platform limit. llama.cpp's own Windows-on-Arm
30+ build, ** same OS, same ggml source** , ships the kernels (` i8mm 244, dotprod 1,052 ` ). Ollama doesn't fork
31+ ggml: it builds pinned upstream llama.cpp with one flag missing. And it is not a Windows quirk either:
32+ the * default* Arm64 build path (` GGML_NATIVE=OFF ` , no ` -march ` ) produces the same cold binary anywhere,
33+ so a mis-built cloud container is one flag away from this.
2734
28- It is not a limitation of the platform. llama.cpp's own Windows-on-Arm build, ** same OS, same ggml
29- source** , ships working kernels (` i8mm 244, dotprod 1,052 ` ). Ollama does not fork ggml's kernels: it
30- fetches upstream llama.cpp pinned by ` LLAMA_CPP_VERSION ` and builds it, with only blob-compatibility
31- patches. The difference is a single missing build flag, and it costs, measured on an Arm Neoverse N2
32- server, ** ~ 6-7x on prompt processing** :
35+ What it costs, measured on ** Azure Cobalt 100 (Neoverse N2)** — a cloud Arm CPU, on the free GitHub
36+ runner, only ` -march ` changing:
3337
34- | build (same model, same N2 hardware, only ` -march ` changes) | coldpath sees | pp512 tok/s | vs COLD |
35- | ---| ---| ---:| ---:|
36- | ** COLD** ` armv8-a ` — what Ollama ships on Windows-on-Arm | i8mm 0, dotprod 0 | ~ 95 | 1.0x |
37- | ** TEPID** ` armv8.2-a+dotprod ` — the safe one-line fix I filed | dotprod 1,044 | ~ 545 | ** ~ 5.75x** |
38- | ** WARM** ` armv8.6-a+i8mm ` | i8mm 268, dotprod 1,044 | ~ 640 | ** ~ 6.7x** |
38+ | build (same model + hardware, only ` -march ` changes) | coldpath sees | pp512 tok/s | tokens / core-hour | vs COLD |
39+ | ---| ---| ---:| ---:| ---: |
40+ | ** COLD** ` armv8-a ` — Ollama's Windows build, and the naive Arm64 default | i8mm 0, dotprod 0 | ~ 95 | ~ 0.34M | 1.0x |
41+ | ** TEPID** ` armv8.2-a+dotprod ` — the one-line fix I filed upstream | dotprod 1,044 | ~ 545 | ~ 1.96M | ** ~ 5.75x** |
42+ | ** WARM** ` armv8.6-a+i8mm ` | i8mm 268, dotprod 1,044 | ~ 640 | ~ 2.30M | ** ~ 6.7x** |
3943
40- _ Representative figures from the [ benchmark workflow ] ( .github/workflows/benchmark.yml ) on the shared
41- Neoverse N2 runner ; they vary a few percent per run and reproduce at ~ 6-7x . The fix I filed upstream is
42- the TEPID row ( dot-product, ~ 5.75x, safe on every Windows-on- Arm device) ; i8mm adds the rest on
43- Snapdragon X ._
44+ _ 5.75x more tokens per core-hour is 5.75x lower cost per token on any Arm cloud. Figures from the
45+ [ benchmark workflow ] ( .github/workflows/benchmark.yml ) ; they vary a few percent per run. The fix I filed
46+ (PR # 17654 ) is the TEPID row — dot-product, safe on every shipped Arm device; i8mm adds the rest where
47+ the silicon has it ._
4448
4549The fix, the root cause, and the reproducible measurement are in
4650[ ` examples/ollama-fix/ ` ] ( examples/ollama-fix/ ) . The benchmark is
@@ -129,10 +133,12 @@ fixes its build, that job fails on purpose.
129133Three findings fall out :
130134
131135**1. Ollama's Windows-on-Arm build has no matrix or dot-product instructions.** Cause and one-line fix
132- in [`examples/ollama-fix/`](examples/ollama-fix/); ~6-7x prefill, measured. Its Linux build is fine
133- (the row above), so this is Windows-specific and build-flag-specific, not Ollama being incapable.
136+ in [`examples/ollama-fix/`](examples/ollama-fix/); ~5.75x prefill from the dot-product fix I filed, up to
137+ ~6.7x with i8mm, measured on Cobalt 100. Its Linux build is fine (the row above), so this is
138+ Windows-specific and build-flag-specific, not Ollama being incapable.
134139
135- **2. Nothing in the ggml ecosystem ships SME — including the backends named for it.** llama.cpp's
140+ **2. No ggml / llama.cpp CPU backend ships SME — including the backends named for it** (ONNX Runtime and
141+ ExecuTorch, in the table above, *do* ship SME by default; this is specific to the ggml stack). llama.cpp's
136142` libggml-cpu-armv9.2_1.so` / `_armv9.2_2.so` are named for the **Armv9.2-A architecture level** (where
137143SME is an *optional* extension), and contain zero ZA-tile instructions, zero `smstart`, zero
138144outer-products. Cause : SME reaches ggml only through KleidiAI, and `GGML_CPU_KLEIDIAI` defaults to
@@ -172,8 +178,8 @@ not a broken detector. `pytest` (24 tests) covers each instruction family agains
172178encodings, the resync-through-data property, the coverage gate, and the single-word corroboration floor,
173179so correctness is provable without any binary on disk.
174180
175- This validation is the receipt, not the headline. The headline is the ~6-7x an Ollama user is silently
176- losing .
181+ This validation is the receipt, not the headline. The headline is the 5.75x more tokens per core-hour
182+ that one build flag recovers on Arm cloud silicon .
177183
178184---
179185
0 commit comments