HelloSun commited on
Commit
176ef13
Β·
1 Parent(s): 5482b0f

experiments: fix -nr methodology (llama-bench needs --repack 0), re-measure #27590 (-nr +0.7%/+1.4%); record #27032 (kernels subset, no gain, not merged) and corrected #18698 incremental (-4.1%/-2.1%, not merged); note -nr vs default on this machine

Browse files
Files changed (1) hide show
  1. README.md +80 -41
README.md CHANGED
@@ -248,7 +248,16 @@ host is noisy, each candidate is measured with an **alternating A/B
248
  protocol**: two binaries built from the same source tree (baseline vs
249
  baseline + candidate patch) are run interleaved in the same session
250
  (`llama-bench -t 16 -r 3 -p 512 -n 128`, default settings, 3–8 rounds each);
251
- the table reports the medians over all rounds.
 
 
 
 
 
 
 
 
 
252
 
253
  Only candidates that win beyond the run-to-run noise are merged into the
254
  patch (βœ… ζœ‰εΉ«εŠ©); candidates without a real gain are recorded here with
@@ -259,8 +268,9 @@ their data and are **not** merged (❌ ζ²’εΉ«εŠ©).
259
  | upstream PR [#27024](https://github.com/ggml-org/llama.cpp/pull/27024) by [@jinzihao](https://github.com/jinzihao) | ggml-cpu/amx: fix the (dead) `block_q8_K` VNNI quantization and enable the VNNI path | βœ… ζœ‰εΉ«εŠ© β€” merged | 57.25 β†’ 59.20 (**+3.4 %**) | 10.94 β†’ 11.24 (**+2.7 %**) |
260
  | upstream PR [#22525](https://github.com/ggml-org/llama.cpp/pull/22525) by [@HyeongiJeon](https://github.com/HyeongiJeon) | ggml-cpu: optimize `ggml_gemm_q4_K_8x8_q8_K` interleaving/staging for AVX-512 (and AVX2) | βœ… ζœ‰εΉ«εŠ©οΌˆprefillοΌ‰β€” merged | 55.78 β†’ 57.42 (**+2.9 %**) | 10.70 β†’ 10.87 (+1.5 %, neutral) |
261
  | upstream PR [#19706](https://github.com/ggml-org/llama.cpp/pull/19706) by [@Manogna-Sree](https://github.com/Manogna-Sree) | Q6_K block interleaving for x86 SIMD (AVX-512/AVX2) | ❌ ζ²’εΉ«εŠ© β€” not merged | 58.16 β†’ 58.34 (+0.3 %) | 11.06 β†’ 11.07 (+0.1 %) |
262
- | upstream PR [#27590](https://github.com/ggml-org/llama.cpp/pull/27590) by [@SongXiaoXi](https://github.com/SongXiaoXi) | ggml-cpu: add AVX-512/VNNI paths for Q5_K/Q6_K dot products | βœ… ζœ‰εΉ«εŠ©οΌˆ`-nr`οΌ‰β€” merged | `-nr`: 56.41 β†’ 58.03 (**+2.9 %**) | `-nr`: 10.85 β†’ 11.12 (**+2.5 %**) |
263
- | upstream PR [#18698](https://github.com/ggml-org/llama.cpp/pull/18698) by [@zzjianhui](https://github.com/zzjianhui) | ggml-cpu: repack weights in parallel (OpenMP, NUMA-local thread placement) | ❌ ζ²’εΉ«εŠ©οΌˆζŽ¨θ«–η•₯ι€€εŒ–οΌ‰β€” not merged | 55.56 β†’ 54.42 (**βˆ’2.1 %**) | 10.31 β†’ 10.05 (**βˆ’2.5 %**) |
 
264
 
265
  Round-by-round for #27024 (candidate vs baseline, t/s):
266
 
@@ -316,59 +326,88 @@ noise. The base `Q3_K_M` model contains only **one** single `Q6_K` tensor,
316
  so a faster Q6_K kernel has almost no weight to act on. The PR is *not*
317
  merged; the data is recorded here for the record. Measured 2026-10-16.
318
 
319
- Round-by-round for #27590 (candidate vs baseline, t/s), `-nr` mode. The
320
- Q5_K/Q6_K dots this PR changes are used on the plain CPU path selected by
321
- `-nr`; with default repacking those weights go through the repack gemv/gemm
322
- kernels instead, and default mode indeed measured neutral
323
- (pp512 βˆ’1.7 % / tg128 +1.0 %, within noise):
324
 
325
  | round | pp512 | tg128 |
326
  |---|---:|---:|
327
- | 1 | 58.03 vs 58.58 | 11.65 vs 11.57 |
328
- | 2 | 57.50 vs 56.41 | 11.57 vs 10.61 |
329
- | 3 | 58.12 vs 56.24 | 11.67 vs 10.85 |
330
- | 4 | 56.88 vs 53.06 | 10.77 vs 9.01 |
331
- | 5 | 58.79 vs 56.58 | 11.12 vs 10.52 |
332
- | 6 | 59.25 vs 56.38 | 11.01 vs 11.14 |
333
- | 7 | 56.81 vs 58.01 | 10.91 vs 11.03 |
334
-
335
- **Verdict βœ… ζœ‰εΉ«εŠ© (`-nr` 樑式, +2.9 % prefill / +2.5 % decode medians,
336
- 5 of 7 rounds won on both).** In this model the PR affects Q5_K (2 tensors,
337
  the dense `ffn_down` of layers 0–1) and Q6_K (1 tensor β€” `output.weight`,
338
- the 388 M-param head that is read on every token). One caveat: the upstream
339
- PR is *closed but never merged* (only an automated AI-content flag, no
340
- review), so it received extra local validation before merging:
 
341
 
342
  - perplexity on a fixed corpus: 1.0354 β†’ 1.0354 (identical)
343
  - `test-backend-ops -b CPU -o MUL_MAT -p 'type=q5_K|type=q6_K'` passes
344
 
345
- Merged. Measured 2026-10-16.
 
346
 
347
- Round-by-round for #18698 (candidate vs baseline, t/s), default settings.
348
- This PR repacks the quantized weights in parallel with OpenMP and pins each
349
- repack thread NUMA-local. (Ported by hand: the year-old PR conflicts with the
350
- current tree and depends on the never-merged PR #18239.)
 
351
 
352
  | round | pp512 | tg128 |
353
  |---|---:|---:|
354
- | 1 | 49.98 vs 53.95 | 9.66 vs 10.24 |
355
- | 2 | 53.62 vs 55.84 | 10.05 vs 9.81 |
356
- | 3 | 55.62 vs 55.29 | 9.78 vs 10.38 |
357
- | 4 | 53.57 vs 55.07 | 10.05 vs 10.02 |
358
- | 5 | 51.86 vs 56.78 | 8.98 vs 10.52 |
359
- | 6 | 56.96 vs 54.54 | 11.16 vs 10.05 |
360
- | 7 | 56.67 vs 57.68 | 11.66 vs 11.40 |
361
- | 8 | 55.23 vs 57.70 | 11.25 vs 11.24 |
362
-
363
- **Verdict ❌ ζ²’εΉ«εŠ© (slightly slower, not merged).** Medians: prefill βˆ’2.1 %
364
- (2 W / 6 L) and decode βˆ’2.5 % (3 W / 3 L / 2 T). Side effect worth recording:
365
- the parallel repack cuts model **load** wall time (load + tiny bench, warm
366
- page cache) from 24 s (2/2 runs) to 10 s (2/2 runs) β€” but the inference phase
367
- itself gains nothing, so per the merge rule (real tok/s gains) the candidate
368
- is **not** merged. Correctness: perplexity 1.0361 β†’ 1.0361 (identical), i.e.
369
  the parallel repack produces identical weights; the regression is presumably
370
  a NUMA page-placement effect, not a data error. Measured 2026-10-16.
371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  ## License
373
 
374
  This project (the patch set, `patch.sh` and documentation) is licensed
 
248
  protocol**: two binaries built from the same source tree (baseline vs
249
  baseline + candidate patch) are run interleaved in the same session
250
  (`llama-bench -t 16 -r 3 -p 512 -n 128`, default settings, 3–8 rounds each);
251
+ the table reports the medians over all rounds. Every number is
252
+ **incremental**: each candidate is compared against the **previous merged
253
+ state**, not against the original port.
254
+
255
+ > Methodology fix (2026-10-16): a first attempt measured `-nr` via the
256
+ > `LLAMA_ARG_REPACK=0` env var. `llama-bench` ignores that variable (it has
257
+ > its own parser; only common-arg tools such as `llama-cli` /
258
+ > `llama-perplexity` honor it), so those runs were silently default-mode.
259
+ > The `-nr` entry for #27590 was re-measured with `llama-bench --repack 0`,
260
+ > the flag the tool actually supports.
261
 
262
  Only candidates that win beyond the run-to-run noise are merged into the
263
  patch (βœ… ζœ‰εΉ«εŠ©); candidates without a real gain are recorded here with
 
268
  | upstream PR [#27024](https://github.com/ggml-org/llama.cpp/pull/27024) by [@jinzihao](https://github.com/jinzihao) | ggml-cpu/amx: fix the (dead) `block_q8_K` VNNI quantization and enable the VNNI path | βœ… ζœ‰εΉ«εŠ© β€” merged | 57.25 β†’ 59.20 (**+3.4 %**) | 10.94 β†’ 11.24 (**+2.7 %**) |
269
  | upstream PR [#22525](https://github.com/ggml-org/llama.cpp/pull/22525) by [@HyeongiJeon](https://github.com/HyeongiJeon) | ggml-cpu: optimize `ggml_gemm_q4_K_8x8_q8_K` interleaving/staging for AVX-512 (and AVX2) | βœ… ζœ‰εΉ«εŠ©οΌˆprefillοΌ‰β€” merged | 55.78 β†’ 57.42 (**+2.9 %**) | 10.70 β†’ 10.87 (+1.5 %, neutral) |
270
  | upstream PR [#19706](https://github.com/ggml-org/llama.cpp/pull/19706) by [@Manogna-Sree](https://github.com/Manogna-Sree) | Q6_K block interleaving for x86 SIMD (AVX-512/AVX2) | ❌ ζ²’εΉ«εŠ© β€” not merged | 58.16 β†’ 58.34 (+0.3 %) | 11.06 β†’ 11.07 (+0.1 %) |
271
+ | upstream PR [#27590](https://github.com/ggml-org/llama.cpp/pull/27590) by [@SongXiaoXi](https://github.com/SongXiaoXi) | ggml-cpu: add AVX-512/VNNI paths for Q5_K/Q6_K dot products | βœ… ζœ‰εΉ«εŠ©οΌˆ`-nr`οΌ‰β€” merged | `-nr`: 65.91 β†’ 66.35 (+0.7 %) | `-nr`: 11.16 β†’ 11.32 (**+1.4 %**) |
272
+ | upstream PR [#18698](https://github.com/ggml-org/llama.cpp/pull/18698) by [@zzjianhui](https://github.com/zzjianhui) | ggml-cpu: repack weights in parallel (OpenMP, NUMA-local thread placement) | ❌ ζ²’εΉ«εŠ©οΌˆζŽ¨θ«–ι€€εŒ–οΌ‰β€” not merged | 56.93 β†’ 54.58 (**βˆ’4.1 %**) | 10.67 β†’ 10.45 (**βˆ’2.1 %**) |
273
+ | draft PR [#27032](https://github.com/ggml-org/llama.cpp/pull/27032) by [@lexasub](https://github.com/lexasub) | CPU optimizations (GET_ROWS+ADD fusion, `get_rows` fast paths, tokenizer, KV-cell rework) β€” only the ggml-kernel subset is portable onto this tree | ❌ ζ²’εΉ«εŠ©οΌˆδΈι©η”¨ζ–Όζœ¬ζ¨‘εž‹οΌ‰β€” not merged | 56.64 β†’ 56.88 (+0.4 %) | 10.82 β†’ 10.73 (βˆ’0.8 %) |
274
 
275
  Round-by-round for #27024 (candidate vs baseline, t/s):
276
 
 
326
  so a faster Q6_K kernel has almost no weight to act on. The PR is *not*
327
  merged; the data is recorded here for the record. Measured 2026-10-16.
328
 
329
+ Round-by-round for #27590 (candidate vs baseline, t/s), `-nr` mode
330
+ (`llama-bench --repack 0`). The Q5_K/Q6_K dots this PR changes are used on
331
+ the plain CPU path selected by `-nr`; with default repacking those weights go
332
+ through the repack gemv/gemm kernels instead (default-mode incremental
333
+ measured ~neutral, within noise):
334
 
335
  | round | pp512 | tg128 |
336
  |---|---:|---:|
337
+ | 1 | 67.88 vs 67.80 | 11.17 vs 11.15 |
338
+ | 2 | 66.08 vs 66.46 | 11.46 vs 11.18 |
339
+ | 3 | 66.01 vs 65.34 | 11.32 vs 11.19 |
340
+ | 4 | 66.63 vs 65.36 | 11.33 vs 11.12 |
341
+
342
+ **Verdict βœ… ζœ‰εΉ«εŠ© (`-nr` 樑式, +0.7 % prefill / +1.4 % decode medians;
343
+ decode won 4 of 4 rounds).** In this model the PR affects Q5_K (2 tensors,
 
 
 
344
  the dense `ffn_down` of layers 0–1) and Q6_K (1 tensor β€” `output.weight`,
345
+ the 388 M-param head that is read on every token), so the consistent decode
346
+ win matches the expectation. One caveat: the upstream PR is *closed but never
347
+ merged* (only an automated AI-content flag, no review), so it received extra
348
+ local validation before merging:
349
 
350
  - perplexity on a fixed corpus: 1.0354 β†’ 1.0354 (identical)
351
  - `test-backend-ops -b CPU -o MUL_MAT -p 'type=q5_K|type=q6_K'` passes
352
 
353
+ Merged. Re-measured 2026-10-16 with the correct `--repack 0` flag (see
354
+ methodology note above).
355
 
356
+ Round-by-round for #18698 (candidate vs baseline = current HEAD i.e. all
357
+ merged patches, t/s), default settings. This PR repacks the quantized
358
+ weights in parallel with OpenMP and pins each repack thread NUMA-local.
359
+ (Ported by hand: the year-old PR conflicts with the current tree and depends
360
+ on the never-merged PR #18239.)
361
 
362
  | round | pp512 | tg128 |
363
  |---|---:|---:|
364
+ | 1 | 54.24 vs 56.40 | 10.48 vs 10.35 |
365
+ | 2 | 55.50 vs 57.92 | 10.37 vs 10.67 |
366
+ | 3 | 54.58 vs 56.93 | 10.45 vs 10.87 |
367
+
368
+ **Verdict ❌ ζ²’εΉ«εŠ© (clear prefill regression, not merged).** Medians:
369
+ prefill βˆ’4.1 % (0 W / 3 L) and decode βˆ’2.1 % (1 W / 2 L); an earlier 5-round
370
+ block against the same effective baseline agreed on prefill (βˆ’2.7 %,
371
+ 1 W / 4 L) with noisy decode. Side effect worth recording: the parallel
372
+ repack cuts model **load** wall time (load + tiny bench, warm page cache)
373
+ from 24 s (2/2 runs) to 10 s (2/2 runs) β€” but the inference phase itself
374
+ gets slower, so per the merge rule (real tok/s gains) the candidate is
375
+ **not** merged. Correctness: perplexity 1.0361 β†’ 1.0361 (identical), i.e.
 
 
 
376
  the parallel repack produces identical weights; the regression is presumably
377
  a NUMA page-placement effect, not a data error. Measured 2026-10-16.
378
 
379
+ Round-by-round for draft #27032 (candidate vs baseline = current HEAD, t/s),
380
+ default settings. The draft bundles several optimizations (GET_ROWS+ADD
381
+ fusion, `get_rows` fast paths, tokenizer, KV-cell rework). The KV/batch and
382
+ tokenizer parts are either **not portable** (rooted in a pre-refactor
383
+ KV-cell design that conflicts with this tree) or not measurable with this
384
+ protocol; only the disjoint ggml CPU-kernel subset could be ported and
385
+ tested:
386
+
387
+ | round | pp512 | tg128 |
388
+ |---|---:|---:|
389
+ | 1 | 57.49 vs 56.64 | 10.73 vs 10.82 |
390
+ | 2 | 56.88 vs 58.68 | 10.85 vs 10.75 |
391
+ | 3 | 55.71 vs 56.50 | 10.35 vs 10.95 |
392
+
393
+ **Verdict ❌ ζ²’εΉ«εŠ© (not applicable to this model, not merged).** β‰ˆΒ±1 % on
394
+ both metrics, PPL identical (1.0361). The reason follows from the graph and
395
+ kernel dispatch: (1) the GET_ROWS+ADD fusion needs an ADD node immediately
396
+ after a GET_ROWS node β€” this model's graph has no such pattern; (2) the
397
+ optimized Q4_K dequant path is not used (`token_embd` is Q3_K); (3) the
398
+ remaining `get_rows` cache-hit path only helps repeated 1-row gathers, which
399
+ this workload barely has. Recorded for the record. Measured 2026-10-16.
400
+
401
+ ### `-nr` vs default on this machine
402
+
403
+ Side observation from the re-anchoring session: on this AMX machine the
404
+ plain-CPU (`-nr`) path is clearly faster than the default repack path.
405
+ HEAD (all merged patches): pp512 56.93 β†’ 66.35 (**+16.6 %**) and tg128
406
+ 10.67 β†’ 11.32 (**+6.1 %**) with `--repack 0` (3–4 interleaved rounds each,
407
+ 2026-10-16). The repack kernels used by default have no AMX path, while the
408
+ plain Q4_KΓ—Q8_K kernels use AMX (boosted further by #27024). On AMX-class
409
+ machines it is worth testing `-nr` for ~+15 % prefill.
410
+
411
  ## License
412
 
413
  This project (the patch set, `patch.sh` and documentation) is licensed