|
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
5.91 kB
| # 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。方法學上兩件事必須先講清楚: | |
| 1. 這條曲線**不用 mlock**(理由見上),no-swap 的保證只保留給 8 GiB 這個部署目標。 | |
| 2. **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. 這個量測**沒有**證明的事 | |
| 1. **不是 cgroup 驗證。** 這個環境的 cgroup2 掛載唯讀、沒有 `CAP_SYS_ADMIN`, | |
| 所以做不到 `memory.max=8G` + `memory.swap.max=0`。目前的保證是 | |
| 「kernel `RLIMIT_DATA` + 取樣殺行程」與「mlock 匿名頁」兩條腿。 | |
| 要做到與 cgroup 完全等價,需要在有 `CAP_SYS_ADMIN` 的主機上跑 | |
| (`docker run --memory=8g --memory-swap=8g`,進容器後確認 | |
| `memory.max=8589934592`、`memory.swap.max=0`)。 | |
| 2. **主機 swap 是開啟的。** no-swap 由 `mlock` 讓它不可能發生,不是把主機的 | |
| swap 關掉。主機層級的 swap 行為沒有被測到。 | |
| 3. **`brk()` 主堆疊未被鎖**(glibc 內部直接下 syscall)。大型配置都走 `mmap`。 | |
| 4. **共享主機**,單輪抖動可達 25%。 | |
| 5. **只驗到 4K context**;模型原生支援 262 K。 | |
| 6. **只做文字推論。** vision projector 是另一個檔案,沒有測。 | |
| 7. **儲存裝置比歷史量測的機器快一到兩個數量級。** | |
| 完整方法與原始資料見 `bench/results/`。 | |
| ## 6. 重現 | |
| ```bash | |
| # 受管治的單次執行 | |
| 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 | |
| ``` |