File size: 9,158 Bytes
7263337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# 任務簡報(Prompt):重現「openPangu-2.0-Flash × llama.cpp v0.7.0 移植 + CPU 優化」專案

> 把這整份文件當作任務書交給一個具備 shell / git / 網路存取能力的 coding agent,
> 在一台 x86 CPU 機器上逐步完成。所有數字都是「本專案在我們的機器上」的參考值,
> 重現時應以你自己的基準量測為準(百分比方向應相近,絕對值依機器而異)。

## 一、任務目標

1. 把 openPangu-2.0-Flash 的 llama.cpp 支援,從舊 fork **手工移植**到最新的
   **llama.cpp v0.7.0**(commit `620d2225cc436ab0b001e3200e590e3b286ef9ab`, 2026-10-15)。
2. 逐一實驗一批**上游 CPU 加速 PR**,用嚴謹的 A/B 協議量測,**只有真實有幫助的才併入**。
3. 把全部結果(含失敗實驗)寫成 model card,打包成 `diff + patch.sh`,
   上傳到 HuggingFace repo:**`HelloSun/llama.cpp-openPangu-2.0-Flash`**。

## 二、素材與來源

| 項目 | 位置 |
|---|---|
| 待移植的原始 fork | `https://github.com/mrexodia/llama.cpp-openPangu-2.0-Flash`(HEAD `76c92350b`,基於 llama.cpp `6f4f53f2b`, 2026-06-29) |
| 移植目標 base | llama.cpp v0.7.0,commit `620d2225cc436ab0b001e3200e590e3b286ef9ab` |
| 模型 | `openPangu-2.0-Flash-base-Q3_K_M.gguf`(92B MoE、約 6B active、512K context、40.7 GiB);另有 split MTP draft head `openPangu-2.0-Flash-mtp-Q8_0.gguf`(Q8_0) |
| 模型下載 | `https://huggingface.co/mrexodia/openPangu-2.0-Flash-GGUF` |
| 最終上傳 repo | `https://huggingface.co/HelloSun/llama.cpp-openPangu-2.0-Flash`(需 HF token) |

## 三、環境與限制

- CPU:Intel Xeon Platinum 8559C(Emerald Rapids,**有 AMX**)、2 NUMA nodes。
- RAM 充足(TiB 級),但有**記憶體上限規則**:任何單一程式 RSS 不得超過 64 GiB、
  總和 80 GiB,超過會被砍(exit 137)。→ 全程使用 **Q3_K_M**(40.7 GiB)量化;
  `default + MTP draft` 會超上限、跑不了(要記錄這件事)。
- Host 是共享機器、噪音 ±2–4% → **所有效能比較必須同場 interleaved 交替量測**。
- 工具怪癖:`bc`、`/usr/bin/time` 可能缺失(用 `$SECONDS` 或 python 計時);
  `llama-cli` 極小 `-c 512` 的 decode 異常慢(用 `-c 8192` 做 E2E smoke);
  v0.7.0 的 `llama-cli` 沒有 `-no-cnv` 旗標(用 `-p` 單輪模式)。

## 四、工作流程

### 步驟 1:移植(port)

- 在 v0.7.0 base 上逐步搬遷 fork 的 openpangu-v2 支援(逐檔手工適配,
  別整包 cherry-pick,v0.7.0 的 KV-cache / batch / graph 都已重構)。
- **已知坑(必須修)**:原始 fork 在 AMX 機器以 default 設定啟動會
  `GGML_ASSERT(*cur_backend_id != -1)`(`sched_reserve` 階段)——根因是 AMX
  weight repacking 對 batched/3D 權重的打包 bug。移植時修掉它,讓 default 可跑。
- 正確性錨點:`llama-perplexity -m <Q3_K_M> -f <小型文字語料> -c 2048 -t 16`
  → 記下基準 PPL(本專案為 **1.0361**;絕對值取決於語料,重現時以「候選與基準
  必須完全相同」為準)。每次併入優化後都要重跑確認相同。

### 步驟 2:建立效能基準

- 基準指令:`llama-bench -m <Q3_K_M> -t 16 -r 3 -p 512 -n 128 [--repack 0]`
- 原始移植的參考值(本機):default `pp512 ≈ 57 / tg128 ≈ 10.9`,
  `-nr`(`--repack 0`)`pp512 ≈ 62–64 / tg128 ≈ 10.5–11`。

### 步驟 3:A/B 協議(每個候選 PR 都照做)

1. 從**上一個已併入狀態**的源碼分別建兩個 binary:
   `bin_base`(baseline)與 `bin_cand`(baseline + 該 PR)。
2. 同一場 session 內**交替執行** base/cand(各 3 輪以上),取中位數與每輪勝負
   (0.5% 內算平手)。
3. 增量 = **vs 前一個已併入狀態**(不是 vs 原始移植!),逐 PR 疊加才準。
4. 正確性:PPL 與基準完全相同;受影響 kernel 跑
   `test-backend-ops -b CPU -o MUL_MAT -p 'type=<qX_K>'` 子集。
5. **只併入真實 positive**;negative 只記錄數據,不併入。
6. 重要陷阱:**`llama-bench` 不吃 `LLAMA_ARG_REPACK=0` 環境變數**
   (只認 `--repack 0` CLI flag;env 變數對 llama-cli/perplexity 有效)。

### 步驟 4:候選清單與已知結論(重現時應得到相近方向)

| PR | 內容 | 本專案結論(增量 t/s) |
|---|---|---|
| [#27024](https://github.com/ggml-org/llama.cpp/pull/27024) | AMX q8_K VNNI gemv | ✅ 併入(pp +3.4% / tg +2.7%) |
| [#22525](https://github.com/ggml-org/llama.cpp/pull/22525) | q4_K AVX-512 GEMM interleave/staging | ✅ 併入(pp +4.0% / tg +4.9%) |
| [#19706](https://github.com/ggml-org/llama.cpp/pull/19706) | Q6_K interleave gemm | ❌ 不併(≈ 0,重測仍近似噪音) |
| [#27590](https://github.com/ggml-org/llama.cpp/pull/27590) | Q5_K/Q6_K AVX-512/VNNI dot | ✅ 併入(`-nr` 下 pp +0.7% / tg +1.4%,4/4 輪勝;上游已關閉未合併,本地驗證) |
| [#18698](https://github.com/ggml-org/llama.cpp/pull/18698) | repack 平行化 + NUMA affinity | ❌ 不併(pp −4.1% / tg −2.1% 回歸;但載入時間 24s→10s;手工移植版存檔備查) |
| [#27032](https://github.com/ggml-org/llama.cpp/pull/27032) | draft:GET_ROWS+ADD 融合、get_rows fast path 等 | ❌ 不併(只有 ggml kernel 子集可移植,≈ 中性;此模型圖中無相鄰 GET_ROWS→ADD、`token_embd` 是 Q3_K,機制無用武之地) |
| [#27396](https://github.com/ggml-org/llama.cpp/pull/27396) | draft:speculative draft-model prefill(EAGLE3/DFlash/GLM4) | ❌ 不適用(CPU 端不用投機解碼、MTP 在 CPU 是淨虧;7/17 檔衝突) |

- 融合/移植技巧:可只取 PR 中可獨立套用的子集(例如
  `git apply --include='ggml/*'`),再單獨驗證。
- 若某 PR 3-way apply 衝突太多、機制與本模型圖不符 → 判「不適用、未移植」,
  寫進 model card 即可,不要硬改核心。

### 步驟 5:收尾實驗(重要發現,要寫進 card)

- 最終組合 A/B(vs 原始移植,同一 session,3 輪):本專案得到
  default **pp +1.2% / tg +3.4%**(每項 3/3 輪勝);
  `-nr` **pp +6.4% / tg +0.6%**。
- **`-nr` vs default**:本 AMX 機器上 `-nr` 明顯更快,
  `pp512 +16.6% / tg128 +6.1%`(default 的 repack kernels 沒有 AMX 路徑)。
- MTP draft head 在 CPU 上是**淨虧**(4.7 vs 11.5+ t/s),純記錄。

### 步驟 6:測試整合與驗收(shipped 樹必須全綠)

1. 新 arch 加入後,完整 `ctest` 常見兩個既有缺口,需修:
   - `test-generate-models`(test-llama-archs):把 openpangu-v2 標為
     MoE-mandatory、補齊其必需 hparams(MLA 幾何 `key/value_length_mla`、
     hyper-connection trio、`attention.sink_count` / `conv_kernel_size`、
     per-layer `attention.layer_swa_window`,fixture 層數 ≥ 4,
     讓損壞態還原測試(rf)在寫入前被 metadata 檢查攔下)。
   - `llama-model-saver`:補寫 `attention.sink_count` /
     `attention.conv_kernel_size` / `attention.layer_swa_window`,
     否則合成模型存檔後無法重載(`test-llama-context` 全紅)。
   - `test-llama-context` 的 `replay` case:K sink prefix 只支援 unified
     cache(多 stream 會 GGML_ABORT)→ 加 per-case skip
     (`arch_requires_unified_kv`,比照既有 `arch_reserves_single_seq` 寫法)。
2. 驗收標準:`ctest` **61/61 全過**;`test-llama-context --models` 對 132 個
   合成模型 **132/132 通過**。
3. 全新 E2E:乾淨目錄 → `./patch.sh`(下載 v0.7.0 tarball、套 diff)→ 建置 →
   PPL 與基準相同 → bench spot-check → `llama-cli -c 8192 -p ...` 能生成。

## 五、交付物與上傳要求

最終 HF repo 應包含:

- `llama.cpp-openpangu-v0.7.0.diff` — 完整 patch(本專案最終:48 檔、
  +3340 / −368)
- `patch.sh` — 下載 pinned commit、套 patch、印建置與執行說明
- `README.md` — model card:
  - 移植說明、與原 fork 的相容性/效能比較(原 fork 在 AMX default 會 abort)
  - 逐 PR 表格,**每個機制標「⭕ 有幫助 / ❌ 沒幫助」並列出前後 tok/s**
  - 測試環境、測試結果、專有名詞(TW 用語)
- `LICENSE` + `LICENSE.header` — **GPL-3.0**(patch 集本身),
  內含使用來源的 MIT 參考清單:llama.cpp、mrexodia fork、ggml、
  以及**有被併入的**上游 PR(#27024 @jinzihao、#22525 @HyeongiJeon、
  #27590 @SongXiaoXi)——未被併入的 PR 不列入引用清單。
- 上傳節奏:**每測完一個機制就分階段上傳一次** HF(commit 訊息記清楚該階段
  內容);最後一次為最終版(diff + README + patch.sh + LICENSE + 本 prompt)。

## 六、成功標準(Definition of Done)

1. `patch.sh` 在乾淨 v0.7.0 上:套用成功 → 建置成功 → 載入模型正確生成
   (PPL 與基準相同)。
2. 完整 `ctest` 全綠(含 openpangu 相關 fixtures 與 context cases)。
3. Model card 完整記錄**全部**實驗(成功與失敗都有數據、結論與原因)。
4. HF repo 內含所有交付物且與本地檔案一致(雜湊一致)。