3並發146 t/s @105K nvfp4:Qwen3.8-27B RTX 5090 滿載實測 II,全 nvfp4 450K pool、419K 全上卡零 offload
-
0. 先給結論
項目 結果 本篇測什麼 上一篇測「真實 agent 負載 13.7 小時」,這篇純速度:prefill / decode 在 DSH compact 上限下的壓力曲線(含 NInfer 近期新增的 nvfp4 KV feature)、官方 docs 方法學對照、並發度對照 Server --kv-dtype nvfp4 --kv-capacity 450560 --max-concurrency 3 --max-context 262144 --spec mtp(RTX 5090 單卡,CUDA 13.3,build 21a0e85f)Prefill 行為 嚴格 FIFO 串行:TTFT = 隊列位置 × 該路的 solo prefill 時間; --max-concurrency完全不加速 prefillSolo prefill 47k → 6,004 tok/s;105k → 4,096;143k → 3,403;157k → 3,174;210k → 2,587 tok/s 壓力 TTFT ladder(s1,C=3,每路 105k) 25.7 / 53.3 / 81.2 s(= solo × 1/×2/×3) C=3 vs C=4(同一 104k workload) C4 多一路(101.7 s),prefill 斜率不變;C4 的真實成本 = parent session 被擠到 host 冷層 → 維持 C=3 docs/performance.md 對照 MTP0 prefill +0.3…+3.4%、decode −1.8…−4.9%;MTP3 per-fixture 最大偏差 −7.6%(在參考值 1σ 內);makespan C4 +7.2%、C8 −17.8%(本 build C8 不再 memory-throttled,avg batch 3.32 vs 參考 2.36)→ 零回歸 C=3 最佳 context size 131,072:compact 上限 104,857 × 3 路並發 + 本 session = 419,428 ≤ 450,560 pool,全 device 容納、零 host offload(s1 實測) 一句話:prefill 是串行的,context 上限是算出來的——C=3 + 131,072 + nvfp4 450K pool 是這顆卡上「3 路滿載並發 + 活的 agent session」全在 device 的最大窗口。
1. 跟上一篇的分別
上一篇(lcz.me/topic/1228,13.7 小時真實編程負荷,int8 KV)的結論是「agent 負載 98.6% 是 prefill,最佳 C=2」。這篇換三個變量:
- KV 換 nvfp4——NInfer 近期新增的 feature(
--kv-dtype nvfp4,上一篇的路線還是 int8 KV);pool 從 262,144 提到 450,560 tokens(reservation 省約 1 GiB,token 容量反而多 73%); - 把 context 窗口鎖在 DSH 實際會觸發 compact 的上限(
floor(0.8 × contextWindow),thresholdRatio 0.8)去壓力測試,而不是拍一個整數; - 拿官方
docs/performance.md的完整方法學(MTP0 長 prompt profile + MTP3 corpus × C=1/2/4/8)跑一遍,跟發布參考值逐項對。
2. 環境與測法
項目 內容 模型 / artifact qwen3.8-27b nvfp4,21,492,695,040 bytes(20.02 GiB) Server(壓力段) --max-context 262144 --kv-dtype nvfp4 --kv-capacity 450560 --max-concurrency 3 --pending-timeout-ms 600000 --spec mtp --draft-tokens 3 --lm-head-draft --prefill-chunk 1024KV pool 450,560 tokens = 7,040 page groups(max 12,288),reservation 9.89 GiB,slack ≈0.96 GiB;host 冷層 8 GiB / 8 state slots 壓力輸入 隨機字/十六進制/數字文本,獨立 seed × 每 scenario;校準 100 KB ≈ 47,663 tokens(0.47 tok/byte,tokenizer 最壞情況) 測法 base 先 solo 一條量 solo 速度;其餘各路同時提交;TTFT / prefill / decode 全部取 engine log 的 status=done行(engine-measured,非 client 牆鐘)零中斷保證 每段 90s grace → kill → VRAM<4000MiB 確認 → 跑 → trap restore EXIT;全程 /health guard;本 DSH session 就在該 server 上解碼,壓力窗口內照常工作(prefix cache hit 55,923 tok)Doc campaign 完全照 docs/performance.md:INT8 KV、 --no-prefix-reuse、max-context 131,072、--kv-capacity auto、stochastic(temp 0.6 / top-p 0.95 / top-k 20 / presence 1.0)、30 fixtures × 5 seeds、fixed shuffle3. 壓力測試:s1–s4 + C4

3-1. TTFT ladder(各路同時提交,engine-measured)
Scenario C 每路 tokens Solo base 並發 TTFT ladder(s) s1(131k line) 3 104,846–105,648 26.4 s / 4,096 tok/s 25.7 / 53.3 / 81.2 s4(145k target) 3 142,186–143,900 44.6 s / 3,403 tok/s 45.5 / 91.1 / 136.5 C4 對照 4 104,122–104,452 ≈4,358 tok/s(全新 server) 23.9 / 49.8 / 75.8 / 101.7 s2 2 156,860–157,804 49.6 s / 3,174 tok/s 49.9 / 101.9(第 3 條排隊) s3 2 210,376–210,854 81.5 s / 2,587 tok/s 81.6 / 165.5(第 3 條排隊) 每條線都恰好是 solo prefill 時間 × 1/×2/×3——prefill 嚴格 FIFO 串行,每路都在用 solo 速度跑。所以 TTFT 的規劃公式非常簡單:
TTFT(第 k 條) ≈ k × (prompt_tokens / solo_prefill_tps)。3-2. Solo prefill 隨 context 遞減

prompt tokens 47k 105k 143k 157k 210k prefill tok/s 6,004(全新 server 6,241) 4,096 3,403 3,174 2,587 TTFT 7.6–8.0 s 26.4 s 44.6 s 49.6 s 81.5 s 3-3. Decode
256-token 短 output 下,每路 95–146 tok/s(MTP3)。output 太短 batching 收益未完全展開;長 output 的數字見第 5 節 doc campaign(155–419 tok/s)。
3-4. Pool 從不 OOM、從不排隊阻塞
所有壓力窗口
materializing=0、無 pool-queue 等待、零 request 失敗。s3 / s4(pool 被 3×157k / 3×143k 占滿)的實際代價是:閒置的 parent session(就是這篇所在的 DSH 對話)被 dematerialize 到 host 冷層(host_active_ms 小幅抬升),它後續的請求照常完成。s1(3×105k + session ≈ 419k ≤ 450,560)則完全沒有 offload——全部狀態留 device。4. C=3 vs C=4(同一 104k workload)
路(FIFO 序) C=3 TTFT C=4 TTFT 1 25.7 s 23.9 s 2 53.3 s 49.8 s 3 81.2 s 75.8 s 4 (無) 101.7 s C4 的 prefill 略快(≈4,358 vs ≈4,090 tok/s)是因為那是全新、無 resident session 的 server,不是並發度帶來的——斜率(每路的 solo 時間)兩邊一樣。C=4 的真實成本:4 路占滿 pool 後 parent session 被擠到 host 層。結論:維持 C=3。
5. docs/performance.md 對照官方發布值
方法學完全照搬(INT8 KV / 131,072 / kv-capacity auto / stochastic / fixed shuffle / 75 requests per point)。
5-1. MTP0 context-length profile(Long NIAH,n=5)

prompt tokens Prefill ref → ours Decode ref → ours 7,680 8,340.4 → 8,621.3(+3.4%) 71.2 → 69.3(−2.7%) 64,512 5,297.9 → 5,315.7(+0.3%) 65.7 → 63.7(−3.1%) 130,048 3,544.7 → 3,635.0(+2.5%) 59.6 → 58.5(−1.8%) 260,096 2,203.1 → 2,224.0(+0.9%) 52.9 → 50.3(−4.9%) 5-2. MTP3 corpus makespan(75 requests/point)

C Makespan ref → ours Decode tok/s ref → ours Avg batch ref → ours 1 4,670.3 → 4,446.9(−4.8%) 161.1 → 155.3 1.00 → 1.00 2 2,510.8 → 2,607.1(+3.8%) 294.7 → 279.6 1.98 → 1.96 4 1,647.7 → 1,766.4(+7.2%) 432.9 → 403.1 3.29 → 3.20 8 2,164.9 → 1,780.1(−17.8%) 334.2 → 419.0(+25.4%) 2.36 → 3.32 發布參考值裡 C=8 被 memory pressure 壓到 avg batch 2.36(比 C=4 慢 31%);本 build 的 C=8 avg batch 3.32,已追平 C=4(1,780 vs 1,766 s)。C=4 仍是 makespan 最優點;C=3 是 450K pool + live session 的線上的操作點。 makespan Δ 混雜 stochastic 抽樣長度(decode tokens 690k–746k 各異),decode tok/s 較乾淨。
5-3. MTP3 per-fixture(C=1 point,n=5/fixture)

Fixture Decode ref → ours Acceptance ref → ours aime 01 195.2 → 197.0(+0.9%) 76.0% → 79.3% aime 15 151.4 → 149.4(−1.3%) 56.2% → 56.6% aime 30 167.5 → 154.8(−7.6%) 64.6% → 58.1%(ref 自身 σ=23.7 tok/s,1σ 內) Code(3 fixtures 池化) 194.3 → 188.2(−3.1%) 76.4% → 76.4% Story(3 fixtures 池化) 126.1 → 124.9(−0.9%) 37.4% → 38.2% Translation(3 fixtures 池化) 192.3 → 190.3(−1.0%) 75.0% → 75.5% Structured(3 fixtures 池化) 219.8 → 216.7(−1.4%) 90.8% → 90.9% 最大偏差 −7.6%(aime 30,stochastic 高變異 fixture,在參考值自身 1σ 內),其餘均在 ±3.1%。判定:零回歸。 300/300 requests 完成,無 request / CUDA / OOM 失敗。
6. 為什麼 131,072 是 C=3 的最佳 context
DSH 的自動 compact 在上限 =
floor(0.8 × contextWindow)(thresholdRatio 0.8)觸發;policy 只讀settings.yaml的 contextWindow,從不參考 server 的 model discovery。pool 規劃 = 3 路在上限 + 1 條活的 session 在上限 ≤ 450,560:
contextWindow compact 上限 3 路 + session Pool 450,560 131,072 104,857 3×104,857 + 104,857 = 419,428
容納,margin 31,132196,608 157,286 3×157,286 = 471,858
超 21,298(只能 C=2)262,144 209,715 3×209,715 = 629,145
超 178,585(只能 C=2)實測佐證:s1(3×105k,131k line)
materializing=0、session 全程留 device;s4(3×143k)3 路照跑,session 轉 host 冷層繼續工作。131,072 是「3 路滿載並發 + 活 session 全在 device」的最大窗口。 配置:server 保持--max-context 262144(只作 backstop),DSHsettings.yaml改contextWindow: 131072,host restart 後生效。7. 新發現 / 坑
--max-concurrency不加速 prefill。 NInfer 的 prefill 是 FIFO 串行:每路用 solo 速度跑,TTFT 就是隊位 × solo 時間。並發度只決定「同時能 decode 幾條」。- 改 server
--max-context防不了 compact。 DSH compact policy 只讀settings.yaml的 contextWindow;只把 server 調大,session 照樣在 0.8× 老窗口觸發 compact;走錯方向(server 比 DSH 窗口小)反而會觸發CONTEXT_WINDOW_EXCEEDED→ forced max balanced head reduction + 1 retry 的錯誤路徑。 - Pool overflow 不 OOM、不排隊。 超限時 engine 把最低優先的 resident(閒置 session)dematerialize 到 host 冷層,不是拒絕請求。體感代價 = 那個 session 自己的請求多一點 host 往返。
- 輸入 tokenization 校準:0.47 tok/byte。 隨機字/十六進制/數字是 tokenizer 最壞情況;100 KB ≈ 47.7k tok;600 KB 直接超 262,144 tok(server error)。做 calibration 記得用 ≤100 KB 的切片。
- nvfp4 pool 比 int8 大(nvfp4 KV 是 NInfer 近期新增的 feature,
--kv-dtype nvfp4)。int8 262,144 pool reservation ≈11.20 GiB;nvfp4 450,560 = 9.89–10.21 GiB——省下的 ~1 GiB 直接變成多 73% 的 token 容量。 - C=8 在本 build 不再 memory-throttled(doc campaign:avg batch 3.32 vs 參考 2.36),makespan 比發布值快 17.8%;但 C=4 仍是 makespan 最優。
8. 最終配置
層 值 Server --max-context 262144 --kv-dtype nvfp4 --kv-capacity 450560 --max-concurrency 3 --prefill-chunk 1024 --pending-timeout-ms 600000 --spec mtp --draft-tokens 3 --lm-head-draftKV pool 450,560 tokens(7,040/12,288 page groups),reservation 9.89 GiB DSH settings.yamlcontextWindow: 131072(compact 上限 104,857),thresholdRatio 0.8操作點 C=3:3×104,857 + session 104,857 = 419,428 ≤ 450,560,零 host offload 9. 限制與未測
- 壓力輸入是最壞 tokenization 的隨機文本:真實 prompt 每 byte 更快,但真實 agent 負荷吃 prefix cache(上一篇 97–99% hit)——兩種 workload 的 prefill 數字不要直接互比。
- 壓力段 output 只有 256 tok:batching 的 decode 收益未完全展開;doc campaign 的 4,096+ output 更代表實戰(155–419 tok/s)。
- stochastic 抽樣:per-fixture decode 有 ±5% 級別抽樣噪聲(參考值 aime 30 自身 σ=23.7 tok/s)。
- doc campaign 用 INT8 KV(方法學固定),跟壓力段的 nvfp4 數字不同 pool、不同 dtype,不可直接互比。
- C4 ladder 跑在全新 server(無 resident session),solo baseline 比 s1 快 ~7%(23.9 vs 26.4 s),C3/C4 對照不是嚴格同條件——但結論(斜率不變、成本在 host offload)不受影響。
- WSL2;全部數字可從 serve log 的
status=done行與結果目錄逐項核對。
數據與複現:全部結果目錄在本機 WSL home 下:壓力
~/ninfer_stress_032756/(s1–s3)、~/ninfer_stress_s4_033927/(s4)、~/ninfer_c4_test_083409/(C4);doc campaign~/ninfer_doc_test_20260902_035140/(mtp0_corpus/summary.csv、mtp3_makespan/points/*.json、每 request server jsonl),pointer~/ninfer_doc_test_latest;engine build21a0e85f,docs 參考docs/performance.md。本篇由本地全棧生成:NInfer(自寫引擎)驅動 DeepSeek Harness(agent 框架)跑完全部測試與數據整理,圖表由本地 Python 生成,全部數字可從上述結果目錄與
ninfer_serve.log逐項核對。歡迎複現或打臉。 - KV 換 nvfp4——NInfer 近期新增的 feature(
-
,
T terry 固定了此主题
-
抄作業中....白嫖就是硬道理 感謝~ ^_^
-
剛剛快樂更新完,成功運行中,可惜這架構沒法兩張 5090做TP跑FB16全尺寸....不然會爽到不行
-
,系统 取消固定了此主题