Ling-3.0-flash:EPQ MoE 專家分頁實驗

這是 Ling-3.0-flash Q4_K_M 的 MoE expert paging 實驗,採用 EPQ (MoE Expert Paging + Quantization)命名。模型權重不包含在本 repo,來源為 inclusionAI/Ling-3.0-flash-GGUF 的 Q4_K_M/ 兩個 shard,總計 77,010,144,672 B = 71.72 GiB。

核心機制是:將未啟用的 experts 留在 SSD,將目前路由選中的 experts 讀入有限 RAM arena,再由 CPU 執行量化 MoE 計算。這不是 Sparse Decomposed Quantization; sdq-ling/ 是早期移植留下的 implementation 名稱,對外名稱使用 EPQ。

快速開始

git clone https://huggingface.co/HelloSun/ling30flash-moe-expert-paging-q4
cd ling30flash-moe-expert-paging-q4
./sdq-ling/serve.sh

server 預設在 http://0.0.0.0:22222:

curl -s localhost:22222/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"messages":[{"role":"user","content":"What is the capital of France?"}],"max_tokens":48,"temperature":0}'

也可以指定 pager 預算:

PORT=22222 RAM_BUDGET_MB=32768 ./sdq-ling/serve.sh

模型與路由

下表已對 Q4_K_M-00001-of-00002.gguf 的 GGUF metadata 逐項核對過。

項目 數值 來源
架構 bailingmoe3 GGUF general.architecture
模型檔 77,010,144,672 B = 71.72 GiB 兩 shard 實際檔案大小
MoE experts 41 層、每層 512 experts expert_count=512;41 層 MoE(另 2 層 dense + 1 層 MTP)
每 token 啟用 8 experts;8 組中先選 4 組 expert_used_count=8、expert_group_count=8、expert_group_used_count=4
expert 權重 約 69.46 GiB,占總權重 96.8 % 非 expert 權重 2.26 GiB
量化 gate/up 為 Q4_K;down 為 Q4_K/Q6_K 逐 tensor 檢查
context metadata 262,144 bailingmoe3.context_length

嚴格 RAM 上限實測

每一輪都在核心層硬上限下執行,不是只把數字傳給 pager:

prlimit --data=<level> --nofile=65536 sdq-chat ... --ram-budget-mb <level>

Linux 上 RLIMIT_DATA 涵蓋 brk() 與所有 mmap 的匿名記憶體,超限會直接 OOM。 swap 則在每輪抽樣 /proc/<pid>/status 的 VmSwap,確認為 0。

測試條件:Intel Xeon Platinum 8559C(192 threads)、ctx=2048、ubatch=128、 threads=8、temp=0、每輪生成 48 token、每級重跑 2 次;每輪前以 posix_fadvise(DONTNEED) 把 71.72 GiB 的 shard 逐檔案逐出 page cache。

RAM 上限 結果 arena slots anon 峰值 餘量 RSS 峰值 decode tok/s SSD MiB/tok hot % swap
4 GiB PASS 1.31 GiB 397 3,065 MB 1,031 MB 4,826 MB 3.38 582.2 35.9 0
8 GiB PASS 4.44 GiB 1,340 6,160 MB 2,032 MB 8,250 MB 7.39 64.0 66.7 0
16 GiB PASS 12.43 GiB 3,757 14,100 MB 2,284 MB 16,189 MB 7.46 45.0 67.9 0
32 GiB PASS 28.44 GiB 8,592 29,985 MB 2,784 MB 32,074 MB 7.45 28.8 68.9 0

讀表時請注意三個欄位的差別:

  • anon 峰值是唯一受上限管制的量(smaps_rollup 的 AnonHWM)。所有 PASS 代表這項確實落在上限之內。
  • RSS 峰值較高是預期的:非 expert 權重以 mmap 載入,屬檔案對映頁, RLIMIT_DATA 不管制。這部分可被核心回收,所以不算在 arena 預算裡。
  • tok/s 在本機跨設定不可比:同一設定重複量測跨度可達 ±20 %,主機還有其他租戶。 判斷 arena 價值的依據應是 hot % 與 SSD MiB/tok,這兩項是單調的 (582 → 64 → 45 → 29 MiB/tok)。

淘汰策略實驗:LRU vs Least stale(8/16/32/56/64 GiB)

sdq_pager 現在支援 SDQ_EVICT_POLICY=lru|least_stale:

  • lru(預設):空槽優先;否則在冷頁中挑 last_use 最舊的,熱頁最後才動。
  • least_stale:只淘汰閒置 ≥ SDQ_EVICT_STALE_TOKENS(預設 2 token, 換算 640 次 expert 請求)的頁;合格頁中挑衰減式 freq 最小者,同 freq 再挑最久未用。 找不到合格頁時退回 LRU,保證不會因為「全部都很新」而卡住。

這一節使用 --no-chat 純 completion。原因:本模型的 chat template 會讓基準提示詞 立刻吐出 <|endoftext|><|role_end|>,SDQ_BENCH_NO_EOG=1 再把它補滿 48 token, 整段 decode 就變成重複同一個 EOG token(舊表與 long-128tok 表都是這個情況)。 純 completion 下 48 token 是真實文字。基準提示詞: Write a detailed paragraph about how a mixture-of-experts model routes tokens to expert weights, and why paging those weights from SSD matters. (各級輸出逐字相同;temp=0 且固定 48 token,所以句子會在途中截斷。實際回答與正確性見下一節。)

測試條件:no-AMX build、ctx=2048、ubatch=128、threads=16、48 token、temp=0、 每級 2 次、每輪前逐檔 posix_fadvise(DONTNEED)、SDQ_RESERVE_MB=3600,新增 64 GiB。

RAM 策略 arena (GiB) slots decode tok/s hot % SSD MiB/tok 總 SSD 讀取 evictions anon 峰值 (MB) RSS 峰值 (MB) swap
8 GiB LRU 4.40 1329 3.65 44.1 493.6 36.9 GB 9550 5,948 7,304 0
8 GiB least_stale 4.40 1329 3.85 45.0 481.1 36.4 GB 9382 5,948 7,305 0
16 GiB LRU 12.40 3746 4.17 60.0 272.3 26.8 GB 4053 13,888 15,245 0
16 GiB least_stale 12.40 3746 4.19 59.5 279.6 27.1 GB 4147 13,888 15,245 0
32 GiB LRU 28.40 8581 5.03 66.2 178.8 22.5 GB 880 29,772 31,130 0
32 GiB least_stale 28.40 8581 4.01 66.2 178.8 22.5 GB 880 29,772 31,130 0
56 GiB LRU 52.40 15834 5.17 67.1 165.0 21.9 GB 0 53,600 54,956 0
56 GiB least_stale 52.40 15834 4.75 67.1 165.0 21.9 GB 0 53,600 54,956 0
64 GiB LRU 60.40 18252 5.15 67.1 165.0 21.9 GB 0 61,543 62,899 0
64 GiB least_stale 60.40 18252 5.30 67.1 165.0 21.9 GB 0 61,543 62,901 0

結論:

  1. least_stale 只有在 8 GiB 這種最緊的預算有可重現的收益:hot 44.1 → 45.0 %, SSD 493.6 → 481.1 MiB/tok(−2.5 %),總讀取 36.9 → 36.4 GB,evictions 少 1.8 %。
  2. 16 GiB 方向反轉:least_stale 的 hot 少 0.5 pp、SSD 多 2.7 %。差距不大, 但兩級結論相反,代表它不是穩定優於 LRU 的策略。
  3. 32 GiB 以上策略實質失效:32 GiB 只剩 880 次 eviction(全部來自大槽位壓力), 2-token 視窗內找不到合格頁,least_stale 全部退回 LRU,數字逐位相同; 56/64 GiB 的 evictions 為 0,兩條策略完全無法區分。
  4. 56 GiB 就飽和,64 GiB 沒有額外收益:arena 52.4 GiB/15,834 槽已容納整輪工作集; 64 GiB 的 arena 60.4 GiB/18,252 槽,hot 67.1 %、SSD 165.0 MiB/tok、 總讀取 21.9 GB 全部不變。此工作負載的 RAM 飽和點是 56 GiB。
  5. anon 峰值全部落在預算內、swap 全為 0;64 GiB 的 anon 峰值 61,543 MB、 RSS 峰值 62,901 MB。

更正:舊的 8/16/32/56 GiB 與 128-token 表使用 chat template + 強制 EOG, decode 只量到「重複解 EOG」的路徑,會大幅低估真實文字的 I/O (8 GiB 的 SSD 63.5 → 493.6 MiB/tok、hot 66.7 → 44.1 %)。 舊表的 tok/s 與 hot% 不可與本表直接比較;本表才是真實 completion 的數字。

證據:**完整結果整理 results/RESULTS.md**、 results/memory_levels_ling30flash-policy-8-16-32-56-64g-comparison.md、 ...-lru.json、...-least_stale.json、results/memory_levels_policy_run.log;可重跑腳本 sdq-ling/memory_levels_ling.py --policies lru least_stale --no-chat。

8 GiB 正確性抽測(10 題)

用與上表相同的 8 GiB 設定(arena 4.40 GiB / 1329 槽、expert 全走 SSD), 每題開一個全新行程、先逐檔 posix_fadvise(DONTNEED) 清 page cache, ctx=1024、n=64、temp=0、chat mode。10/10 通過,swap 全為 0, anon 峰值 5,939 MB;decode 3.1–4.5 tok/s。

# 題目 回答 判定
1 What is the capital of France? The capital of France is Paris. PASS
2 What is 17 multiplied by 23? 17 × 23 = 391 PASS
3 What is the chemical symbol for gold? The chemical symbol for gold is Au. PASS
4 How many days are there in a leap year? There are 366 days in a leap year. PASS
5 Which planet is the largest in the Solar System? Jupiter is the largest planet in the Solar System. PASS
6 Who wrote the play Romeo and Juliet? Romeo and Juliet is a famous tragedy written by William Shakespeare. PASS
7 What is the square root of 144? The square root of 144 is 12. PASS
8 水的沸點在標準大氣壓下是多少攝氏度? 水的沸點在標準大氣壓下是100攝氏度。 PASS
9 地球上有幾個大陸? 傳統上,地球上有七個大陸(亞洲、非洲、北美洲、南美洲、南極洲、歐洲、大洋洲)。 PASS
10 What language is primarily spoken in Brazil? Portuguese is the primary language spoken in Brazil. PASS

這個模型的 chat template 會在答案前吐出 <role> / <|endoftext|> 等 token; 上表已移除這些前綴,JSON 保留 answer_raw。

抽測同時抓到 sdq-chat 的一個舊 bug:prefill 後的第一個 token 只被送去 evaluate、 沒有被印出,導致短答案可能整段空白,中文還可能被截成無效 UTF-8。已修正 (sdq_cli.cpp 先印出目前 token 再 submit)並重跑;路由與 I/O 計數不受影響。

證據:results/verify_qa_8g.md、results/verify_qa_8g.json。

4 GiB 與 AMX 的取捨

要在 4 GiB 內啟動,必須關掉 AMX。原因是 -march=native 會定義 __AMX_INT8__,llama.cpp 因此要一塊 1,876.34 MiB 的 AMX repack buffer, 在 4 GiB 內光這一塊就吃掉將近一半預算。

cmake -S llama.cpp -B llama.cpp/build_noamx -DCMAKE_BUILD_TYPE=Release \
  -DLLAMA_CURL=OFF -DGGML_NATIVE=OFF -DGGML_AVX512=ON \
  -DGGML_AVX512_VBMI=ON -DGGML_AVX512_VNNI=ON -DGGML_AVX512_BF16=ON \
  -DGGML_AVX2=ON -DGGML_FMA=ON -DGGML_F16C=ON \
  -DGGML_AMX_INT8=OFF -DGGML_AMX_TILE=OFF -DGGML_AMX_BF16=OFF

上表的 4 GiB 一列使用這個 build;8 GiB 以上兩種 build 都能通過 (AMX build 的 8 GiB 實測 anon 峰值 6,608 MB,修正後預設 SDQ_RESERVE_MB=3600)。

4 GiB 下 arena 只剩 1.31 GiB(397 槽),hot % 掉到 35.9 %、SSD 讀取 582 MiB/tok —— 能跑,但比 8 GiB 慢一個數量級。若預算有 8 GiB,就不要選 4 GiB。

已知陷阱:SDQ_RESERVE_MB 決定成敗

pager::alloc_arena() 在 llama.cpp 載入權重之前就算 arena,此時 rss_now 只有約 0.09 GiB,因此之後長出來的所有匿名配置都必須由 reserve 手動扣掉。這些包含 AMX 模型緩衝(1,876 MiB)、CPU compute buffer (83.5 MiB @ubatch=128)、KV/SSM state 與執行緒堆疊。

舊的預設值 900 MB(舊實驗用 1,024 MB)只涵蓋後三項,漏掉 AMX buffer。 實測結果:

SDQ_RESERVE_MB RAM 預算 實際 anon 峰值 結果
1,024 MB 8 GiB 10.96 GiB 超出上限,OOM
3,600 MB 8 GiB 6.61 GiB PASS
2,700 MB 4 GiB 3.07 GiB PASS(需關閉 AMX)
2,600 MB 4 GiB — bad_alloc

已將 sdq_pager.cpp、serve.sh、memory_levels_ling.py 的預設值改為 3,600 MB。若你的環境不需要 AMX,可以再往下調以換更多槽位。

I/O 稽核(已重跑)

mincore(2) 掃過整個模型檔,搭配 buffered 對照組:

A:預設(O_DIRECT) B:對照組(buffered + 保留 cache)
真正從 block device 讀入(read_bytes) 23.65 GiB 22.22 GiB
模型檔留在 page cache 的峰值(mincore) 2.095 GiB 22.219 GiB

重跑結果與原版一致(2.09 / 22.2 GiB)。2.095 GiB 就是非 expert 權重; 對照組證明這個量測有鑑別力。69.46 GiB 的 expert 權重沒有任何一個位元組進過 page cache。

正確性(已重跑)

檢查 結果
單 expert 前向 × 7 層 vs 純 NumPy 7/7 PASS,max_rel ≤ 0.019,corr ≥ 0.99982(重跑數值與原版逐位元相同)
真實圖上整層 MoE(routing + 加權)vs NumPy PASS,corr 0.99988
NumPy dequant vs ggml dequantize_row_* 21/21 列逐位元組相同

更正:原 final_results.md 宣稱整層驗證做了 layer 3 與 layer 20, 但當時只留下 layer 20 的輸出。單 expert 測試(verify_selftest.txt)本來 就涵蓋 layer 3,兩邊都有。

限制與注意事項

  • RAM budget 與硬性上限不同。--ram-budget-mb 只影響 arena sizing; 要真正設限必須靠 OS(memory.max、RLIMIT_DATA)。上表已用後者驗證。
  • 本 repo 的量測環境沒有可用的 GPU(容器內 nvidia-smi 無法初始化), 全部為 CPU 執行。
  • /sys/fs/cgroup 在此容器為唯讀,無法再切子 cgroup,因此用 prlimit 施加上限;RLIMIT_DATA 對匿名記憶體的管制語意與 memory.max 相同, 但不包含 page cache。
  • 8 GiB 以上的主機也可改用原生全載入路徑(需約 71.72 GiB RAM)。
  • Q4_K_M 在 greedy near-tie prompt 可能有量化輸出差異。
  • 模型權重授權與使用條件請以 upstream model card 為準。

證據

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for HelloSun/ling30flash-moe-expert-paging-q4_EPQ

Finetuned
(1)
this model