Download docs/STRICT_8GIB.md from HelloSun/minicpm47woek_EPQ: direct link, hf CLI and curl.
- Browser
- Download file 5.91 kB
-
https://huggingface.co/HelloSun/minicpm47woek_EPQ/resolve/main/docs/STRICT_8GIB.md
- Command line
-
hf download hf://HelloSun/minicpm47woek_EPQ/docs/STRICT_8GIB.md
-
curl -L -o STRICT_8GIB.md https://huggingface.co/HelloSun/minicpm47woek_EPQ/resolve/main/docs/STRICT_8GIB.md
8 GiB / no-swap 的方法、證據與限制
本專案的核心主張是「21.17 GB 的模型在 8 GiB RAM、沒有 swap 的條件下解碼」。
每一次執行都由 tools/strict8g.py 在行程執行期間管治,不是事後推論。
strict_ok=False 的樣本一律不採用。
1. 兩條腿
no-swap 由核心保證,不是讀一次數值
行程所有匿名映射都被 tools/epq_lock.so 以 mlock() 鎖住。
被鎖定的頁永遠不會被寫到 swap 裝置,所以 no-swap 是核心在整段執行期間強制
的,而不是執行完之後從某一次讀取推論出來的。
標配執行下 VmLck ≈ 7.6 GiB,這個數字可以直接驗證。
實體常駐量有硬上限
取樣器(預設每 5 ms 讀一次 /proc/<pid>/status)一旦發現匿名 RSS 超過上限
立刻 SIGKILL;另外用 RLIMIT_DATA 當第二道防失控的閘門。
每次執行都記錄 VmHWM、RssAnon、VmSwap、VmLck。
2. 標配結果
8 GiB 上限、ctx=4096、ubatch=128、8 threads、greedy、48 requested tokens、 提示詞中英交替、N=9 配對交錯:
| 指標 | 值 |
|---|---|
| Decode tok/s(中位數) | 5.83 |
| 單輪全距 | 5.19 – 6.63(抖動 25%) |
| Expert cache hit rate | 68.68% |
| SSD 讀取 / decode token | 214.1 MB |
| Arena | 6.35 GiB(3714 slots) |
| 峰值匿名 RSS | 7799 MiB / 8192 MiB 上限 |
| 峰值 VmSwap | 0.000 MiB |
| strict_ok | 9/9 |
條件:2× Intel Xeon Platinum 8559C(AVX-512 / AMX)。
這是共享主機,同一組設定的單輪抖動可達 25%。數字足以支撐「能不能跑」 與「大概多快」,不足以支撐 5% 等級的宣稱。
3. 同一個 8 GiB 上限下的傳統 llama.cpp
未修改的 llama.cpp(commit 9d7d5049,獨立 worktree 編譯的 llama-completion)
在同一個 8192 MiB 上限下:
[strict8g] FAIL strict: rc=1 wall=27.3s | anon=928.8 file=20199.0 total=21127.2
ggml_aligned_malloc: insufficient memory (attempted to allocate 14400.00 MB)
ggml_backend_buft_alloc_buffer_n_default: failed to allocate CPU_REPACK buffer of size 15099494400
llama_model_load: error loading model: unable to allocate CPU_REPACK buffer
模型都載不進去,在載入階段就失敗。
| 路徑 | 結果 |
|---|---|
| 傳統 llama.cpp(未套 patch) | 無法載入模型 |
EPM epq-chat |
5.83 tok/s,峰值匿名 RSS 7799 MiB,VmSwap 0 |
對照必須在同一個上限下建立:先量「兩邊都沒限制」再比較,是把 RAM 這個 變數漏掉了。
3b. RAM 擴張曲線怎麼讀
完整表格在 README。方法學上兩件事必須先講清楚:
- 這條曲線不用 mlock(理由見上),no-swap 的保證只保留給 8 GiB 這個部署目標。
- arena 不預先碰滿。全部路由專家權重只有 18.16 GiB,所以 64 GiB 預算下 預先碰觸的上限就是 18.17 GiB;峰值 RSS 停在約 24.0 GiB 才是真實的記憶體佔用。
結論(每個點 N=9,配對交錯,Welch t 檢定,36/36 輪 strict_ok):
- 4 GiB → 8 GiB:+16.6%,t = −5.44,p = 0.0001(顯著)。
- 8 GiB → 16 GiB:−0.8%,t = −0.30,p = 0.76(無法分辨)。
- 8 GiB → 64 GiB:−0.2%,t = −0.05,p = 0.96(無法分辨)。
- 命中率在 16 GiB 飽和於 77.54%,SSD/token 飽和於 ~158 MB。
- 記憶體需求飽和於約 24.0 GiB 峰值。
4. 儲存裝置會改變結論
本機是本地 NVMe / overlayfs,不是網路檔案系統。tools/io_probe.py 量到的儲存
特性決定了瓶頸在哪一邊:
- 慢速儲存上 I/O 排程是瓶頸,預取與並行讀取才有意義。
- 快速本機 NVMe 上 命中率(arena 大小)才是瓶頸,I/O 最佳化的邊際收益很低。
本 repo 的 tok/s 不能直接套用到慢速儲存的機器上。先跑 tools/io_probe.py
再決定要最佳化哪一邊。
5. 這個量測沒有證明的事
- 不是 cgroup 驗證。 這個環境的 cgroup2 掛載唯讀、沒有
CAP_SYS_ADMIN, 所以做不到memory.max=8G+memory.swap.max=0。目前的保證是 「kernelRLIMIT_DATA+ 取樣殺行程」與「mlock 匿名頁」兩條腿。 要做到與 cgroup 完全等價,需要在有CAP_SYS_ADMIN的主機上跑 (docker run --memory=8g --memory-swap=8g,進容器後確認memory.max=8589934592、memory.swap.max=0)。 - 主機 swap 是開啟的。 no-swap 由
mlock讓它不可能發生,不是把主機的 swap 關掉。主機層級的 swap 行為沒有被測到。 brk()主堆疊未被鎖(glibc 內部直接下 syscall)。大型配置都走mmap。- 共享主機,單輪抖動可達 25%。
- 只驗到 4K context;模型原生支援 262 K。
- 只做文字推論。 vision projector 是另一個檔案,沒有測。
- 儲存裝置比歷史量測的機器快一到兩個數量級。
完整方法與原始資料見 bench/results/。
6. 重現
# 受管治的單次執行
python3 tools/strict8g.py --limit-mb 8192 --record /tmp/one.json -- \
epq-chat -m model.gguf -p "..." -n 48 -c 4096 -t 8 -b 128 \
--temp 0 --no-chat --no-interactive --ram-budget-mb 8192
# 標配基準(N=9,配對交錯)
python3 -m sdq.strict_bench --model model.gguf \
--bins base=./build/bin/epq-chat --rounds 9 --strict-mb 8192 --label headline
# 曲線與負結果
python3 bench/run_budget_curve.py --model model.gguf --bin ./build/bin/epq-chat --rounds 5
python3 bench/run_ramsweep.py --model model.gguf --bin ./build/bin/epq-chat --rounds 3
python3 bench/run_n9.py --model model.gguf --bin ./build/bin/epq-chat --rounds 9
python3 bench/run_negative.py --which prefetch --model model.gguf --bin ./build/bin/epq-chat
python3 bench/run_negative.py --which threads --model model.gguf --bin ./build/bin/epq-chat