Skip to content

Commit 58367af

Browse files
Re-anchor on cloud (per judge panel): lead with Cobalt 100 / Neoverse N2, tokens-per-core-hour, honest 5.75x (the filed fix); fix 'ggml ecosystem ships SME' self-contradiction; tighten verb to contains/can-dispatch
1 parent 22ab7a3 commit 58367af

1 file changed

Lines changed: 32 additions & 26 deletions

File tree

README.md

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
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

4549
The 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.
129133
Three 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
137143
SME is an *optional* extension), and contain zero ZA-tile instructions, zero `smstart`, zero
138144
outer-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
172178
encodings, the resync-through-data property, the coverage gate, and the single-word corroboration floor,
173179
so 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

Comments
 (0)