DEV Community

Cover image for ggml 1.0.0: 13 APIs gone, CPU speed unchanged
frank chu
frank chu

Posted on

ggml 1.0.0: 13 APIs gone, CPU speed unchanged

ggml 1.0.0: 13 APIs gone, CPU speed unchanged

ggml 1.0.0 deletes 13 public API functions, removes two ops, and bumps the RPC protocol to v9. I built it and its predecessor from source and benched both on CPU: text generation is identical — 19.8 tokens a second on both — and prompt processing is inside the noise everywhere I measured. The first 1.x release is a cleanup release, not a speed release, at least on a CPU-only box.

What 1.0.0 actually is

ggml 1.0.0 landed on November 13, 2026, nine days after v0.29.0. The diff between the two tags is 299 files changed, 16,891 lines added and 6,801 removed. Most of the additions are GPU backends: few-row quantized matmuls and MoE fusion on CUDA, a Vulkan prefill FlashAttention path, a device-side MoE scheduler on SYCL, decomposed Adreno FlashAttention in OpenCL, new WebGPU kernels. The headline CPU changes are smaller: MUL_MAT switched to F32 src1, FlashAttention V now accumulates in F32, and the scheduler skips uploading inputs that no op reads.

The breaking part is the API. include/ggml.h shrank by 276 lines (7 added). I counted 13 removed GGML_API declarations:

Removed Status
ggml_diag_mask_inf, ggml_diag_mask_inf_inplace Deleted outright, with the GGML_OP_DIAG_MASK_INF op
ggml_diag_mask_zero, ggml_diag_mask_zero_inplace Deleted outright, with the GGML_OP_DIAG_MASK_ZERO op
ggml_type_sizef Deleted outright
ggml_rope_yarn_corr_dims Deleted outright
ggml_add1, ggml_add1_inplace Deprecated, now removed
ggml_mul_mat_set_prec Deprecated, now removed — replaced by ggml_prec_set_acc
ggml_rope_custom, ggml_rope_custom_inplace Deprecated, now removed
ggml_upscale_ext, ggml_flash_attn_ext_set_prec Deprecated, now removed

New in their place: ggml_rope_set_truncate / ggml_rope_get_truncate for YaRN correction-bound rounding, and a backward pass for the TRI op. The RPC protocol went to v9, and the release notes say it rejects incompatible peers — an old llama-server talking to a new one will fail the handshake instead of silently misbehaving.

How I measured

I built llama.cpp twice from source with identical flags (cmake -DGGML_NATIVE=ON -DCMAKE_BUILD_TYPE=Release, GNU 13.3.0): master at commit 3de52ac (November 4, 2026, version string 0.9.0-dev) and master at commit e574a17 (November 15, version string 1.0.0-dev). Before trusting the comparison I checked that the old tree's ggml.h is byte-identical to the ggml v0.29.0 tag and the new tree's is byte-identical to the v1.0.0 tag. Both diffs came back empty — the bench really is 0.29.0 vs 1.0.0.

Machine: AMD EPYC 9D25, 4 vCPUs, no GPU. Model: Qwen2.5-0.5B-Instruct Q4_K_M, 491,400,032 bytes — I verified the size against Hugging Face's content-length exactly, and parsed the GGUF header myself (general.file_type 15, which llama.h defines as MOSTLY_Q4_K_M). llama.cpp counts 630.17M parameters, not 494M, because the file carries an untied output.weight alongside token_embd.weight — both 151,936 × 896. Each config ran through llama-bench at 4 threads, first in 3 repetitions, then again in 5, and I report both rounds.

The scoreboard

Prompt processing (pp) and generation (tg), tokens per second, mean ± stddev across repetitions:

Test 0.29.0 (3 reps) 1.0.0 (3 reps) 0.29.0 (5 reps) 1.0.0 (5 reps)
pp128 76.90 ± 4.06 74.19 ± 5.48 77.78 ± 14.65 70.43 ± 21.87
pp512 83.71 ± 3.85 93.68 ± 0.90 87.73 ± 4.39 91.14 ± 10.64
tg128 19.45 ± 0.86 20.05 ± 2.23 19.62 ± 0.86 19.95 ± 5.49
tg128 (2nd config) 20.99 ± 0.66 19.36 ± 3.14 19.30 ± 2.89 19.75 ± 2.86

Pooled across both rounds: generation is 19.84 tok/s on 0.29.0 and 19.78 on 1.0.0 — a 0.3% difference on four measurements each, which is no difference at all. Prompt processing at 128 tokens is pure noise (pooled 77.3 vs 72.3, with standard deviations up to ±21.9). At 512 tokens the pooled means are 85.7 vs 92.4, about +7.8% — but the error bars overlap in both rounds, so I won't call it a win. If you squint, the F32 src1 change plausibly helps compute-bound prompt processing at longer contexts; generation on CPU is memory-bandwidth-bound, so nothing there was ever going to move.

The takeaway

On this box, 1.0.0 buys you nothing in speed and costs you 13 API functions. That's not a complaint — it's what a 1.0 is for. The deprecated functions had been deprecated for a reason, the DIAG_MASK ops were legacy, and the RPC bump is the kind of break you want to take exactly once, at a major version. The performance work in this release is real, it's just almost all on GPU backends this machine doesn't have. If you run llama.cpp on CPU, upgrade for the cleanup and the YaRN truncation controls, not for tokens per second. If you build on ggml's public API, grep for diag_mask, add1, rope_custom, upscale_ext, and mul_mat_set_prec before you upgrade — and if you run RPC workers, upgrade both ends together, because v9 will not talk to v8.

Caveats, stated plainly: one small model (0.5B, quantized), one 4-vCPU shared VM, 3–5 repetitions per config. A 70B model or a GPU would tell a different story about the backend work — the CUDA few-row matmul and Metal MoE fusion changes are exactly the kind of thing that shows up there and not here.

Sources: ggml v1.0.0 release notes (github.com/ggml-org/ggml/releases/tag/v1.0.0, November 13, 2026); ggml v0.29.0 tag (November 4, 2026). All bench numbers are my own runs on the machine and builds described above; the API counts are from git diff v0.29.0 v1.0.0 on the ggml repository.

Top comments (0)