7900 XTX 的可能性探索|单卡篇(三):强强联合还是缝合怪?— KVMem × daniel-mtp,快和大可以同时要
-
-
-
-
-
,系统 取消固定了此主题
-
很有意思的東西,但看到以下這些召回率是不是會有不可靠的情況?
能不能測看看對agent調用或開發的影響有多大?Recall发现的问题
500K 级极端 Recall:budget 32768
15 / 20 = 75%budget 65536
18 / 20 = 90%@dardeaw-feng 这个我后来确实补测了,测试的就是 单卡 7900 XTX 上的 Qwen3.8-27B Q4_K_M + KVMem × Daniel MTP在Hermes Agent真实使用的情景。
先看 Agent 工具调用:在约 500K 的 append-only session 里,Chat、Streaming 和 Tool Calls 都跑通了。首次冷启动约 884 秒;基态建好后,每轮只追加约 80 个 token,Prefill 约 0.6 秒,整轮约 2.6–4.3 秒。这个结果说明正常追加式的多轮 Agent 对话和工具调用可以工作。
但改写上下文是另一回事:在约 176K 的热会话中间改约 2,000 个字符,重新 Prefill 花了约 289 秒,接近冷启动。所以前缀不能随便改,遇到这种情况还是会等。这是个大问题,说明缓存命中效率不高。但是我注意到KVMem 主仓库里更新到了0.17.0,它正在补我这两天最关心的那块——长 Session 的 state/prefix reuse。只是ROCm beta2 预编译还没有更新。一旦更新了我会第一时间再补测。
Recall 方面,500K、20 个 needle 的极端测试中,budget 32768 命中 15/20,budget 65536 命中 18/20;主要问题是取错 needle 对应的值,中段表现相对弱。这个结果说明偶尔只出现一次、又要精确绑定的远处信息,确实有漏取风险,但不能直接理解成日常 Agent 有 10% 或 25% 的失败率。主要是我不编程,所有对我来说影响其实不大。
所以目前能说的是:500K 追加式 Agent 工具循环已实测可用;Recall 还不是 100%;真实代码开发成功率还没用类似开发任务单独测过。
事实上,这个“缝合怪”我用起来感觉别的都很好,最大的问题是cold prefill有点太长时间了。虽然归功于DanielMTP这个特调底座,prefill的速度一直保持的很好 (到512K还保持 >660 t/s,见帖子的插图1)但是架不住上下文实在太大了,按 256K 实际约 261,875 tokens、Prefill 700 tok/s 算,完整读入约 374 秒,也就是 6 分 14 秒,这就等于是卡了六分多钟。除非是晚上休息让模型自己跑任务,否则一般情况还是很难忍受经常要卡几分钟的情况(我略微夸张的描述哈,真实使用还好)
-
-
-
KVMem 在 RX 7900 XTX 24GB 上的實測報告
依 lcz.me/topic/1961(《7900 XTX 的可能性探索|单卡篇(二):KVMem 是个好东西》)的測試口徑,在本機復現並實測。
測試日期:2026-09-29
摘要
- KVMem 成功安裝並以 gfx1100 HIP 編譯完成,實測單張 7900 XTX 24GB 跑通 523,214-token prompt(完整 Prefill → Decode → 正常輸出),邏輯上下文 512K。
- VRAM 峰值僅 17.4–19.8 GiB,與原文一致;上下文從 128K 擴到 512K(4 倍),VRAM 幾乎不成長(代價轉到 Host RAM,512K 需約 20–22 GB RSS)。
- KVMem 不只省 VRAM,也比 Full-KV 快:128K 下 prefill 快 ~35%、decode 快 ~60–90%;Full-KV 在 128K 已吃掉 22,478 MiB(MTP ON),512K 在 24GB 卡上不可能。
- 本機數字整體低於原文約 5–28%,已定位原因:本機 7900 XTX 嚴重熱節流(junction 實測 106–107 °C、風扇已 84%、sclk 僅 2519/2634 MHz、功耗僅 179/291 W)。
- Recall 一開始是本機與原文最大的分歧(後來解決了):62K / 256K 都可 20/20(100%),但 519K 只有 10/20(50%)(原文 90%)。找出兩個關鍵:retrieval query 必須來自「最後一個 user turn」,以及加大
--kvmem-budget能直接把 512K recall 拉回 80%。
測試環境
項目 本機 原文 GPU RX 7900 XTX 24GB(gfx1100),另有 R9700 32GB(gfx1201) RX 7900 XTX 24GB ×1 CPU Intel Xeon E5-2696 v3(18C/36T, 2.3 GHz) AMD Ryzen 5 9600X 系統記憶體 46 GiB 64 GB ROCm 7.2.4 7.2.3 OS / kernel Ubuntu 24.04.4 / 7.0.0-34 Linux 模型 Qwen3.8-27B-UD-Q4_K_M.gguf(16 GB, Unsloth,nextn_predict_layers=1)Qwen3.8-27B Q4_K_M 原生 context 262,144 262,144
安裝與編譯
來源與版本
項目 值 Repo https://github.com/kvmem/kvmem-llama.cpp分支 rocm-beta(HEAD1c4eef7)llama.cpp pin submodule b81c99b(2026-09-02)Patch patches/llama-kvmem-current.patch→ 38 個檔案編譯指令
cd kvmem-llama.cpp ROCM_PATH=/opt/rocm python3 scripts/build-rocm.py --linux --gpu-targets gfx1100 --jobs 16 # → build-hip-linux/bin/llama-kvmem-server共 600 個建置目標、0 錯誤。產出
llama-kvmem-server、llama-kvmem-cli、llama-tokenize等。
踩雷與修復:HIP general protection fault(本機特有)
症狀
以
--device ROCm1(7900 XTX)啟動後,第一個請求必崩:traps: llama-kvmem-ser general protection fault ip:... in libamdhip64.so.7.2.70204 exit code 139伺服器日誌沒有任何錯誤訊息。
定位
AMD_LOG_LEVEL=3的 HIP API trace 給出真正原因:hipLaunchKernel ( ... ) Forcing SPIRV: false :1:hip_fatbin.cpp:687: No compatible code objects found for: gfx1201本機有兩張 AMD 卡,而這次只編譯了
gfx1100。llama.cpp 的 HIP backend 在初始化時會列舉所有可見裝置,某些 kernel 被下到 gfx1201(R9700),該架構沒有對應 code object → HIP 在 fatbin 查找失敗時不回報錯誤而是直接 GPF。這正是原文「單卡 7900 XTX」環境不會踩到的地雷。
解法
export ROCR_VISIBLE_DEVICES=1 # 只暴露 7900 XTX(gfx1100 為 device 0) # 之後用 --device ROCm0驗證:
ggml_cuda_init: found 1 ROCm devices (Total VRAM: 24560 MiB): Device 0: Radeon RX 7900 XTX, gfx1100 (0x1100), ... VRAM: 24560 MiB加上後立即恢復正常。其他可行做法:編譯時帶
--gpu-targets gfx1100,gfx1201(兩個 code object 都編進去),或實體只留一張卡。
長上下文實測結果(主矩陣)
測試口徑
llama-kvmem-server -m Qwen3.8-27B-UD-Q4_K_M.gguf --device ROCm0 -ngl 99 --load-mode none \ -c <ctx> -b 2048 -ub 512 -t 6 --flash-attn on \ --kvmem --kvmem-budget 32768 --kvmem-gen-reserve 16384 \ --kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \ [--spec-type draft-mtp --spec-draft-n-max 2 --spec-kv-dtype f16 --kvmem-mtp-state replay] # MTP ON- prompt 長度以
llama-tokenize精確擬合(誤差 ≤ 128 token),非字元估算。 - Decode 一律取 512 個輸出 token 的完整樣本(非短樣本)。
- VRAM = 全卡
mem_info_vram_used峰值;Host RSS = 伺服器行程 VmRSS 峰值。
實測表
Context 標稱 實際 Prompt MTP Prefill (tok/s) Decode (tok/s) TTFT (s) VRAM 峰值 (MiB) Host RSS 峰值 (MiB) 131,072 128K 130,072 OFF 402.37 19.58 324.8 18,757 6,415 131,072 128K 130,072 ON 442.56 45.90 295.3 19,808 7,205 262,144 256K 261,169 OFF 463.59 25.64 565.6 18,804 10,848 262,144 256K 261,169 ON 428.62 46.83 611.4 19,430 12,146 524,288 512K 523,214 OFF 386.33 19.51 1,358.5 18,289 19,845 524,288 512K 523,214 ON 340.57 34.74 1,541.4 19,195 22,021 6/6 全部成功。512K 一檔完成 523,214-token prompt 的完整 Prefill → Decode → 正常輸出(輸出 512 token),非僅「服務能啟動」。
與原文逐項對照
Context MTP Prefill 本機 / 原文 Decode 本機 / 原文 TTFT 本機 / 原文 (s) 128K OFF 402.4 / 557.6(−27.8%) 19.6 / 27.0(−27.4%) 324.8 / 235.0 128K ON 442.6 / 533.9(−17.1%) 45.9 / 36.6(+25.4%) 295.3 / 246.0 256K OFF 463.6 / 532.6(−13.0%) 25.6 / 26.9(−4.8%) 565.6 / 493.0 256K ON 428.6 / 511.7(−16.2%) 46.8 / 36.4(+28.7%) 611.4 / 513.0 512K OFF 386.3 / 520.3(−25.8%) 19.5 / 26.9(−27.3%) 1,358.5 / 1,009.0 512K ON 340.6 / 500.3(−31.9%) 34.7 / 39.8(−12.7%) 1,541.4 / 1,049.0 最關鍵的一點:VRAM 不隨 Context 成長
Context 邏輯 Context 倍數 VRAM 峰值 (MiB) 128K 1× 18,757 256K 2× 18,804 512K 4× 18,289 邏輯上下文放大 4 倍,VRAM 峰值幾乎不變(甚至略降),穩定落在 18–19.8 GiB。這正是 KVMem 的核心價值:GPU 只維持約 32K active KV working set,超出的歷史 KV 落在 Host RAM(RSS 由 6.4 GB 成長到 19.8/22.0 GB)。原文第 5 節的結論在本機完全複現。
為什麼本機數字偏低:熱節流
原文機器(Ryzen 9600X + B850 平台)在同樣 24GB 卡上明顯更快。本機在 512K 滿載時實測:
指標 實測值 說明 Junction 溫度 106–107 °C RDNA3 節流點約 110 °C Edge / Memory 62–63 °C / 70 °C 風扇 2,467 RPM(84%) 已接近上限 sclk 2,519 MHz(上限 2,634 MHz) 未跑滿 功耗 179 W / 291 W 非功耗限制,是溫度限制 同一張卡在冷機(junction 52 °C)起跑時 512K prefill 可達 601 tok/s,隨著溫度爬升一路掉到 344 tok/s,整段平均 340–386 tok/s。這解釋了:
- 本機 prefill 普遍低於原文;
- 同一設定不同次量測變動可達 ±10%(例如 128K MTP OFF 在背景編譯時 402 tok/s、乾淨重測 437 tok/s);
- MTP ON 的超長上下文檔位掉幅最大(512K ON 僅 340.6 tok/s)。
這是本機散熱條件問題(機殼風道/風扇曲線),不是 KVMem 或 ROCm 的問題。原文環境應未觸發節流。
Recall 測試(Needle-in-a-Haystack)
方法:在長文中等距埋入 20 個互不相關的 6 位數字 needle(
NOTE: the reference code for NEEDLE-xx is CCCCCC.),
在文末逐一提問並精確比對 6 位數字。上下文與 GPU budget 可調。關鍵發現:retrieval query 的「請求結構」才是決定性因素
伺服器是用
find_last_user_role_block()從 最後一個 user 訊息 取出 retrieval query
(tools/llama-kvmem-server.cpp:1012)。因此:- 若把 整篇長文 + 問題塞在同一個 user message,query 就變成整篇長文,retrieval 形同亂選;
- 必須把長文放在前一個 user turn,問題單獨當最後一個 user turn,query 才等於真正的問題。
在 62K context 下把 GPU budget 壓到 8192(覆蓋率僅 ~13%),兩種結構的差距立刻暴露:
請求結構 GPU budget Context Recall A:長文+問題同一個 user message 32768 62K 19/20(95%) B:問題單獨為最後 user turn 32768 62K 20/20(100%) A:長文+問題同一個 user message 8192 62K 11/20(55%) B:問題單獨為最後 user turn 8192 62K 20/20(100%) 解讀:budget 大(32768)時 485 個 block 有 256 個留在 GPU(覆蓋率 53%),
即使 retrieval 很爛 A 也有 95%;把 budget 壓到 8192(覆蓋率 13%)後,
A 掉到 55% 而 B 仍是 100% —— 這證明 B 的 retrieval 是精準的,A 的不是。512K 實測
請求結構 Prompt tokens Recall 備註 A:長文+問題同一個 user message 519,198 8/20(40%) query 變成整篇長文 B:問題單獨為最後 user turn 519,195 10/20(50%) query 正確,但語料放大到 519K 後仍退化 觀察:答錯時模型回傳的幾乎都是另一顆 needle 的號碼(如問 NEEDLE-06 答 567730 = NEEDLE-10 的值),
而不是隨機亂答 —— 表示 needle 的 block 有被取回,但取回的是錯的那一顆。
所有 needle 都以同一句型(...reference code for NEEDLE-xx is ...)書寫,彼此高度相似,
在大語料下 retrieval 的排序鑑別力會下降。與原文對照
來源 Context Recall 原文 KVMem ~520K 18/20(90%) 原文 SGLang / NInfer ~520K 100% 本機 KVMem(62K / budget 8192 / 結構 B) 62K 20/20(100%) 本機 KVMem(512K / budget 32768 / 結構 B) 519K 10/20(50%) 【重要】recall 的關鍵變數是「GPU working set 覆蓋率」,不是語料大小
先前 512K 只拿到 50%,一度以為是大語料下的硬限制。後續在 256K / 384K / 512K
三個檔位(其餘參數完全相同:reserve 固定、MTP on、multiturn、同一批 20 顆 needle)
實測後,可看出規律是覆蓋率,而且衰退是平滑的,不是斷崖:Context budget 候選 blocks 取回 blocks 覆蓋率 Recall VRAM 峰值 Host RSS 峰值 62K 8192 484 64 13% 20/20(結構 B) 17,085 — 256K 32768 2,024 256 12.6% 20/20(100%) 18,865 12,695 384K 32768 3,072 256 8.3% 17/20(85%) 18,857 18,261 384K 98304 3,072 768 25% 19/20(95%) 21,291 18,392 512K 32768 4,056 256 6.3% 10/20(50%) 18,289 19,845 512K 98304 4,056 768 19% 16/20(80%) 21,507 23,304 兩個結論:
- 同一個語料,加大
--kvmem-budget就能把 recall 拉回來:512K 由 50% → 80%,
384K 由 85% → 95%。這是本次最實用的調校結論 —— 要保準確度,該調的是 budget,
不是把 context 開更大。 - 384K + budget 98304 是本機長上下文的最佳平衡點:recall 95%、VRAM 21.3 GiB、
Host RSS 只 18.4 GB(ComfyUI 可以不用關),比 512K 那組(80% / 23.3 GB)明顯划算。
MTP 接受率與效益
KVMem 的 server 不輸出 MTP 接受率統計,因此改用
llama-kvmem-cli
以同一種生成任務(編號清單,512 輸出 token)量測。設定 Decode (tok/s) 相對提升 MTP OFF 29.41 — MTP ON ( --spec-draft-n-max 2, F16 draft KV)50.82 +72.8% 伺服器端 MTP 效益(主矩陣)
Context MTP OFF MTP ON Decode 提升 TTFT 變化 128K 19.58 45.90 +134% −29.5 s 256K 25.64 46.83 +83% +45.8 s 512K 19.51 34.74 +78% +182.9 s 本機的 MTP 增益比原文(+35.6~+48.3%)更大,原因是測試任務是高度可預測的編號清單,
接受率偏高。原文的結論方向一致:KVMem 解決容量、MTP 解決速度,兩者可疊加,
但超長 prompt + 短輸出時要注意 TTFT 變差(512K 時 TTFT 多 183 s)。
Full-KV 對照(
--no-kvmem)以相同模型、相同 prompt(130,072 token)、相同 KV dtype(q8_0)、相同 FA / batch / threads 設定,
只把 KVMem 關掉(--no-kvmem,即傳統 Full-KV 全部常駐 GPU):設定 @128K VRAM 峰值 (MiB) Host RSS 峰值 (MiB) Prefill (tok/s) Decode (tok/s) KVMem(budget 32768)MTP OFF 18,757 6,415 402–437 19.6–21.2 Full-KV( --no-kvmem)MTP OFF20,667 1,895 301.8 12.7 KVMem MTP ON 19,808 7,205 424–443 40.7–45.9 Full-KV MTP ON 22,478 2,180 288.8 23.9 差異(MTP OFF / ON) KVMem 少 1.9 / 2.7 GiB KVMem 多 4.5 / 5.0 GiB KVMem 快 ~35% KVMem 快 ~60–90% 原文的 Full-KV 對照(128K):MTP OFF 21,168 MiB、MTP ON 23,008 MiB;
本機 Full-KV 為 20,667 / 22,478 MiB —— 兩者相當吻合(差 2.4%),
可見 KVMem 的 VRAM 節省在兩個環境下是一致的(約 2–3 GiB @128K)。這裡有一個原文沒強調、但很實際的發現
KVMem 不只省 VRAM,還明顯更快。 原因很直接:KVMem 只讓 ~48K token 的
active working set 進 GPU,attention 就只在那個範圍上算;Full-KV 則要在
全部 131K token 上算。所以本機量到 KVMem 的 prefill 快約 35%、decode 快約 60%。容量上的差距更關鍵:
Context KVMem VRAM Full-KV(估計/原文實測) 128K 18,289–19,808 MiB 20,667 MiB(本機實測) 512K 19,195 MiB 依 128K 線性外推約 30–35 GiB → 24GB 卡放不下 也就是說,512K 這件事在原生的 Full-KV 路徑上根本無法成立,這才是 KVMem 的核心價值。
結論
- KVMem 可用且值得用:單張 24GB 7900 XTX 跑通 523,214-token 邏輯上下文,VRAM 僅 18.2–19.8 GiB,速度沒有崩塌(decode 19.5–46.8 tok/s)。原文的核心結論在本機完整複現。
- 最有價值的不是速度,是容量:4 倍上下文、VRAM 幾乎不成長。代價轉移到 Host RAM —— 512K 需要約 20–22 GB 主機 RSS。本機只有 46 GiB,512K 已接近上限(可用 RAM 最低剩 7.1 GiB);原文的 64 GB 餘裕明顯更好。
- KVMem 同時比 Full-KV 快(原文未強調):128K 下 prefill 快 ~35%、decode 快 ~60–90%,因為 attention 只在 ~48K 的 active working set 上計算,而非全部 131K。Full-KV 在 128K 已吃掉 20.7/22.5 GiB,512K 在 24GB 卡上根本無法成立。
- MTP 在超長上下文要算 E2E 帳:本機 MTP ON 對 decode 提升很大(+78~134%),但 TTFT 在 512K 反而多 183 s,與原文結論方向一致。KVMem 與 MTP 可正常疊加。
- 多卡機器要注意:只編譯一個 gfx target 而讓另一個架構的卡保持可見,會導致 HIP GPF 崩潰(本機 gfx1201 + gfx1100);
ROCR_VISIBLE_DEVICES或雙 target 編譯可解。原文的單卡環境不會踩到。 - Recall 的關鍵變數是「GPU working set 覆蓋率」,不是語料大小:256K 可 20/20(100%),384K 掉到 17/20(85%),512K 只剩 10/20(50%)——平滑衰退,不是斷崖。而把
--kvmem-budget從 32768 提到 98304:384K 回到 19/20(95%)、512K 回到 16/20(80%)。另外 retrieval query 必須是「最後一個 user turn」,把長文與問題塞在同一個 user message 會讓 query 變成整段長文,recall 直接掉到 40%。這三點是使用上最容易踩、也最好修的坑。 - 散熱是硬限制:本機 7900 XTX 在滿載時 junction 達 106–107 °C、風扇已 84%、sclk 2519/2634 MHz、功耗僅 179/291 W,明顯已在節流區。這解釋了本機數據普遍低原文 5–28% 且變動大。
實務建議
PROFILE CTX budget reserve Recall 實測 VRAM 峰值 Host RSS 用途 day131072 32768 16384 (62K/256K 都 100%) 19.8 GB 7.2 GB 日常 native262144 32768 16384 20/20(100%) 18.9 GB 12.7 GB 要準、decode 最快 long393216 98304 8192 19/20(95%) 21.3 GB 18.4 GB 長上下文最佳平衡 max524288 98304 8192 16/20(80%) 21.5 GB 23.3 GB 真的需要 512K 時 - 要 recall 準:
PROFILE=long(95%)或native(100%);並把問題放在獨立的 user turn,不要把問題接在超長文件後面同一個 message。 - 要跑 512K:至少先確認散熱(改善風道/機殼風扇),並關掉其他吃 RAM 的服務;46 GiB RAM 是緊繃的。
- 長 session Agent:KVMem 的前綴快取實測有效(512K 下
cache_n=519195,每輪只需 prefill ~500 token),這才是它最實用的場景。
重現指令
# 1) 取得與編譯 cd kvmem-llama.cpp ROCM_PATH=/opt/rocm python3 scripts/build-rocm.py --linux --gpu-targets gfx1100 --jobs 16 # 2) 只暴露 7900 XTX(務必,否則 HIP GPF) export ROCR_VISIBLE_DEVICES=1 # 3) 啟動 512K 服務 ./build-hip-linux/bin/llama-kvmem-server \ -m Qwen3.8-27B-UD-Q4_K_M.gguf \ --device ROCm0 -ngl 99 --load-mode none \ -c 524288 -b 2048 -ub 512 -t 6 --flash-attn on \ --kvmem --kvmem-budget 32768 --kvmem-gen-reserve 16384 \ --kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \ --no-ui # 4) 量測(本報告使用的 harness) python3 bench/ctx_bench.py --binary kvmem-llama.cpp/build-hip-linux/bin/llama-kvmem-server \ --model Qwen3.8-27B-UD-Q4_K_M.gguf \ --out results/x.json --ctx 524288 --target-prompt-tokens 523264 --mtp on -
@dardeaw-feng 这个我后来确实补测了,测试的就是 单卡 7900 XTX 上的 Qwen3.8-27B Q4_K_M + KVMem × Daniel MTP在Hermes Agent真实使用的情景。
先看 Agent 工具调用:在约 500K 的 append-only session 里,Chat、Streaming 和 Tool Calls 都跑通了。首次冷启动约 884 秒;基态建好后,每轮只追加约 80 个 token,Prefill 约 0.6 秒,整轮约 2.6–4.3 秒。这个结果说明正常追加式的多轮 Agent 对话和工具调用可以工作。
但改写上下文是另一回事:在约 176K 的热会话中间改约 2,000 个字符,重新 Prefill 花了约 289 秒,接近冷启动。所以前缀不能随便改,遇到这种情况还是会等。这是个大问题,说明缓存命中效率不高。但是我注意到KVMem 主仓库里更新到了0.17.0,它正在补我这两天最关心的那块——长 Session 的 state/prefix reuse。只是ROCm beta2 预编译还没有更新。一旦更新了我会第一时间再补测。
Recall 方面,500K、20 个 needle 的极端测试中,budget 32768 命中 15/20,budget 65536 命中 18/20;主要问题是取错 needle 对应的值,中段表现相对弱。这个结果说明偶尔只出现一次、又要精确绑定的远处信息,确实有漏取风险,但不能直接理解成日常 Agent 有 10% 或 25% 的失败率。主要是我不编程,所有对我来说影响其实不大。
所以目前能说的是:500K 追加式 Agent 工具循环已实测可用;Recall 还不是 100%;真实代码开发成功率还没用类似开发任务单独测过。
事实上,这个“缝合怪”我用起来感觉别的都很好,最大的问题是cold prefill有点太长时间了。虽然归功于DanielMTP这个特调底座,prefill的速度一直保持的很好 (到512K还保持 >660 t/s,见帖子的插图1)但是架不住上下文实在太大了,按 256K 实际约 261,875 tokens、Prefill 700 tok/s 算,完整读入约 374 秒,也就是 6 分 14 秒,这就等于是卡了六分多钟。除非是晚上休息让模型自己跑任务,否则一般情况还是很难忍受经常要卡几分钟的情况(我略微夸张的描述哈,真实使用还好)
@Ben-Lee
你這命中率偏低,因為llama.cpp的前綴你要深挖優化,弄到增量以外都能命中,
冷啟動還好,把顯存的ctx弄到ssd去吧,我以前玩llama.cpp都這樣幹,對話id跟模型當key就好,但要客製處理前綴的時間戳記,KVMem底子就是llama.cpp一定可以
Recall 先天就是中段(40-60% 深度)最弱:文件正中間的資訊召回率比頭尾差,那就是產生幻覺,但你論述上"不編程沒影響"有個矛盾....不編程的話根本不需要太大的KV呀?那KVMem存在的意義就很薄弱了。建議上git+codegraph給harness做輔助讓他不用看整段代碼,可以彌補長文本的中段弱點。 -
KVMem 在 RX 7900 XTX 24GB 上的實測報告
依 lcz.me/topic/1961(《7900 XTX 的可能性探索|单卡篇(二):KVMem 是个好东西》)的測試口徑,在本機復現並實測。
測試日期:2026-09-29
摘要
- KVMem 成功安裝並以 gfx1100 HIP 編譯完成,實測單張 7900 XTX 24GB 跑通 523,214-token prompt(完整 Prefill → Decode → 正常輸出),邏輯上下文 512K。
- VRAM 峰值僅 17.4–19.8 GiB,與原文一致;上下文從 128K 擴到 512K(4 倍),VRAM 幾乎不成長(代價轉到 Host RAM,512K 需約 20–22 GB RSS)。
- KVMem 不只省 VRAM,也比 Full-KV 快:128K 下 prefill 快 ~35%、decode 快 ~60–90%;Full-KV 在 128K 已吃掉 22,478 MiB(MTP ON),512K 在 24GB 卡上不可能。
- 本機數字整體低於原文約 5–28%,已定位原因:本機 7900 XTX 嚴重熱節流(junction 實測 106–107 °C、風扇已 84%、sclk 僅 2519/2634 MHz、功耗僅 179/291 W)。
- Recall 一開始是本機與原文最大的分歧(後來解決了):62K / 256K 都可 20/20(100%),但 519K 只有 10/20(50%)(原文 90%)。找出兩個關鍵:retrieval query 必須來自「最後一個 user turn」,以及加大
--kvmem-budget能直接把 512K recall 拉回 80%。
測試環境
項目 本機 原文 GPU RX 7900 XTX 24GB(gfx1100),另有 R9700 32GB(gfx1201) RX 7900 XTX 24GB ×1 CPU Intel Xeon E5-2696 v3(18C/36T, 2.3 GHz) AMD Ryzen 5 9600X 系統記憶體 46 GiB 64 GB ROCm 7.2.4 7.2.3 OS / kernel Ubuntu 24.04.4 / 7.0.0-34 Linux 模型 Qwen3.8-27B-UD-Q4_K_M.gguf(16 GB, Unsloth,nextn_predict_layers=1)Qwen3.8-27B Q4_K_M 原生 context 262,144 262,144
安裝與編譯
來源與版本
項目 值 Repo https://github.com/kvmem/kvmem-llama.cpp分支 rocm-beta(HEAD1c4eef7)llama.cpp pin submodule b81c99b(2026-09-02)Patch patches/llama-kvmem-current.patch→ 38 個檔案編譯指令
cd kvmem-llama.cpp ROCM_PATH=/opt/rocm python3 scripts/build-rocm.py --linux --gpu-targets gfx1100 --jobs 16 # → build-hip-linux/bin/llama-kvmem-server共 600 個建置目標、0 錯誤。產出
llama-kvmem-server、llama-kvmem-cli、llama-tokenize等。
踩雷與修復:HIP general protection fault(本機特有)
症狀
以
--device ROCm1(7900 XTX)啟動後,第一個請求必崩:traps: llama-kvmem-ser general protection fault ip:... in libamdhip64.so.7.2.70204 exit code 139伺服器日誌沒有任何錯誤訊息。
定位
AMD_LOG_LEVEL=3的 HIP API trace 給出真正原因:hipLaunchKernel ( ... ) Forcing SPIRV: false :1:hip_fatbin.cpp:687: No compatible code objects found for: gfx1201本機有兩張 AMD 卡,而這次只編譯了
gfx1100。llama.cpp 的 HIP backend 在初始化時會列舉所有可見裝置,某些 kernel 被下到 gfx1201(R9700),該架構沒有對應 code object → HIP 在 fatbin 查找失敗時不回報錯誤而是直接 GPF。這正是原文「單卡 7900 XTX」環境不會踩到的地雷。
解法
export ROCR_VISIBLE_DEVICES=1 # 只暴露 7900 XTX(gfx1100 為 device 0) # 之後用 --device ROCm0驗證:
ggml_cuda_init: found 1 ROCm devices (Total VRAM: 24560 MiB): Device 0: Radeon RX 7900 XTX, gfx1100 (0x1100), ... VRAM: 24560 MiB加上後立即恢復正常。其他可行做法:編譯時帶
--gpu-targets gfx1100,gfx1201(兩個 code object 都編進去),或實體只留一張卡。
長上下文實測結果(主矩陣)
測試口徑
llama-kvmem-server -m Qwen3.8-27B-UD-Q4_K_M.gguf --device ROCm0 -ngl 99 --load-mode none \ -c <ctx> -b 2048 -ub 512 -t 6 --flash-attn on \ --kvmem --kvmem-budget 32768 --kvmem-gen-reserve 16384 \ --kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \ [--spec-type draft-mtp --spec-draft-n-max 2 --spec-kv-dtype f16 --kvmem-mtp-state replay] # MTP ON- prompt 長度以
llama-tokenize精確擬合(誤差 ≤ 128 token),非字元估算。 - Decode 一律取 512 個輸出 token 的完整樣本(非短樣本)。
- VRAM = 全卡
mem_info_vram_used峰值;Host RSS = 伺服器行程 VmRSS 峰值。
實測表
Context 標稱 實際 Prompt MTP Prefill (tok/s) Decode (tok/s) TTFT (s) VRAM 峰值 (MiB) Host RSS 峰值 (MiB) 131,072 128K 130,072 OFF 402.37 19.58 324.8 18,757 6,415 131,072 128K 130,072 ON 442.56 45.90 295.3 19,808 7,205 262,144 256K 261,169 OFF 463.59 25.64 565.6 18,804 10,848 262,144 256K 261,169 ON 428.62 46.83 611.4 19,430 12,146 524,288 512K 523,214 OFF 386.33 19.51 1,358.5 18,289 19,845 524,288 512K 523,214 ON 340.57 34.74 1,541.4 19,195 22,021 6/6 全部成功。512K 一檔完成 523,214-token prompt 的完整 Prefill → Decode → 正常輸出(輸出 512 token),非僅「服務能啟動」。
與原文逐項對照
Context MTP Prefill 本機 / 原文 Decode 本機 / 原文 TTFT 本機 / 原文 (s) 128K OFF 402.4 / 557.6(−27.8%) 19.6 / 27.0(−27.4%) 324.8 / 235.0 128K ON 442.6 / 533.9(−17.1%) 45.9 / 36.6(+25.4%) 295.3 / 246.0 256K OFF 463.6 / 532.6(−13.0%) 25.6 / 26.9(−4.8%) 565.6 / 493.0 256K ON 428.6 / 511.7(−16.2%) 46.8 / 36.4(+28.7%) 611.4 / 513.0 512K OFF 386.3 / 520.3(−25.8%) 19.5 / 26.9(−27.3%) 1,358.5 / 1,009.0 512K ON 340.6 / 500.3(−31.9%) 34.7 / 39.8(−12.7%) 1,541.4 / 1,049.0 最關鍵的一點:VRAM 不隨 Context 成長
Context 邏輯 Context 倍數 VRAM 峰值 (MiB) 128K 1× 18,757 256K 2× 18,804 512K 4× 18,289 邏輯上下文放大 4 倍,VRAM 峰值幾乎不變(甚至略降),穩定落在 18–19.8 GiB。這正是 KVMem 的核心價值:GPU 只維持約 32K active KV working set,超出的歷史 KV 落在 Host RAM(RSS 由 6.4 GB 成長到 19.8/22.0 GB)。原文第 5 節的結論在本機完全複現。
為什麼本機數字偏低:熱節流
原文機器(Ryzen 9600X + B850 平台)在同樣 24GB 卡上明顯更快。本機在 512K 滿載時實測:
指標 實測值 說明 Junction 溫度 106–107 °C RDNA3 節流點約 110 °C Edge / Memory 62–63 °C / 70 °C 風扇 2,467 RPM(84%) 已接近上限 sclk 2,519 MHz(上限 2,634 MHz) 未跑滿 功耗 179 W / 291 W 非功耗限制,是溫度限制 同一張卡在冷機(junction 52 °C)起跑時 512K prefill 可達 601 tok/s,隨著溫度爬升一路掉到 344 tok/s,整段平均 340–386 tok/s。這解釋了:
- 本機 prefill 普遍低於原文;
- 同一設定不同次量測變動可達 ±10%(例如 128K MTP OFF 在背景編譯時 402 tok/s、乾淨重測 437 tok/s);
- MTP ON 的超長上下文檔位掉幅最大(512K ON 僅 340.6 tok/s)。
這是本機散熱條件問題(機殼風道/風扇曲線),不是 KVMem 或 ROCm 的問題。原文環境應未觸發節流。
Recall 測試(Needle-in-a-Haystack)
方法:在長文中等距埋入 20 個互不相關的 6 位數字 needle(
NOTE: the reference code for NEEDLE-xx is CCCCCC.),
在文末逐一提問並精確比對 6 位數字。上下文與 GPU budget 可調。關鍵發現:retrieval query 的「請求結構」才是決定性因素
伺服器是用
find_last_user_role_block()從 最後一個 user 訊息 取出 retrieval query
(tools/llama-kvmem-server.cpp:1012)。因此:- 若把 整篇長文 + 問題塞在同一個 user message,query 就變成整篇長文,retrieval 形同亂選;
- 必須把長文放在前一個 user turn,問題單獨當最後一個 user turn,query 才等於真正的問題。
在 62K context 下把 GPU budget 壓到 8192(覆蓋率僅 ~13%),兩種結構的差距立刻暴露:
請求結構 GPU budget Context Recall A:長文+問題同一個 user message 32768 62K 19/20(95%) B:問題單獨為最後 user turn 32768 62K 20/20(100%) A:長文+問題同一個 user message 8192 62K 11/20(55%) B:問題單獨為最後 user turn 8192 62K 20/20(100%) 解讀:budget 大(32768)時 485 個 block 有 256 個留在 GPU(覆蓋率 53%),
即使 retrieval 很爛 A 也有 95%;把 budget 壓到 8192(覆蓋率 13%)後,
A 掉到 55% 而 B 仍是 100% —— 這證明 B 的 retrieval 是精準的,A 的不是。512K 實測
請求結構 Prompt tokens Recall 備註 A:長文+問題同一個 user message 519,198 8/20(40%) query 變成整篇長文 B:問題單獨為最後 user turn 519,195 10/20(50%) query 正確,但語料放大到 519K 後仍退化 觀察:答錯時模型回傳的幾乎都是另一顆 needle 的號碼(如問 NEEDLE-06 答 567730 = NEEDLE-10 的值),
而不是隨機亂答 —— 表示 needle 的 block 有被取回,但取回的是錯的那一顆。
所有 needle 都以同一句型(...reference code for NEEDLE-xx is ...)書寫,彼此高度相似,
在大語料下 retrieval 的排序鑑別力會下降。與原文對照
來源 Context Recall 原文 KVMem ~520K 18/20(90%) 原文 SGLang / NInfer ~520K 100% 本機 KVMem(62K / budget 8192 / 結構 B) 62K 20/20(100%) 本機 KVMem(512K / budget 32768 / 結構 B) 519K 10/20(50%) 【重要】recall 的關鍵變數是「GPU working set 覆蓋率」,不是語料大小
先前 512K 只拿到 50%,一度以為是大語料下的硬限制。後續在 256K / 384K / 512K
三個檔位(其餘參數完全相同:reserve 固定、MTP on、multiturn、同一批 20 顆 needle)
實測後,可看出規律是覆蓋率,而且衰退是平滑的,不是斷崖:Context budget 候選 blocks 取回 blocks 覆蓋率 Recall VRAM 峰值 Host RSS 峰值 62K 8192 484 64 13% 20/20(結構 B) 17,085 — 256K 32768 2,024 256 12.6% 20/20(100%) 18,865 12,695 384K 32768 3,072 256 8.3% 17/20(85%) 18,857 18,261 384K 98304 3,072 768 25% 19/20(95%) 21,291 18,392 512K 32768 4,056 256 6.3% 10/20(50%) 18,289 19,845 512K 98304 4,056 768 19% 16/20(80%) 21,507 23,304 兩個結論:
- 同一個語料,加大
--kvmem-budget就能把 recall 拉回來:512K 由 50% → 80%,
384K 由 85% → 95%。這是本次最實用的調校結論 —— 要保準確度,該調的是 budget,
不是把 context 開更大。 - 384K + budget 98304 是本機長上下文的最佳平衡點:recall 95%、VRAM 21.3 GiB、
Host RSS 只 18.4 GB(ComfyUI 可以不用關),比 512K 那組(80% / 23.3 GB)明顯划算。
MTP 接受率與效益
KVMem 的 server 不輸出 MTP 接受率統計,因此改用
llama-kvmem-cli
以同一種生成任務(編號清單,512 輸出 token)量測。設定 Decode (tok/s) 相對提升 MTP OFF 29.41 — MTP ON ( --spec-draft-n-max 2, F16 draft KV)50.82 +72.8% 伺服器端 MTP 效益(主矩陣)
Context MTP OFF MTP ON Decode 提升 TTFT 變化 128K 19.58 45.90 +134% −29.5 s 256K 25.64 46.83 +83% +45.8 s 512K 19.51 34.74 +78% +182.9 s 本機的 MTP 增益比原文(+35.6~+48.3%)更大,原因是測試任務是高度可預測的編號清單,
接受率偏高。原文的結論方向一致:KVMem 解決容量、MTP 解決速度,兩者可疊加,
但超長 prompt + 短輸出時要注意 TTFT 變差(512K 時 TTFT 多 183 s)。
Full-KV 對照(
--no-kvmem)以相同模型、相同 prompt(130,072 token)、相同 KV dtype(q8_0)、相同 FA / batch / threads 設定,
只把 KVMem 關掉(--no-kvmem,即傳統 Full-KV 全部常駐 GPU):設定 @128K VRAM 峰值 (MiB) Host RSS 峰值 (MiB) Prefill (tok/s) Decode (tok/s) KVMem(budget 32768)MTP OFF 18,757 6,415 402–437 19.6–21.2 Full-KV( --no-kvmem)MTP OFF20,667 1,895 301.8 12.7 KVMem MTP ON 19,808 7,205 424–443 40.7–45.9 Full-KV MTP ON 22,478 2,180 288.8 23.9 差異(MTP OFF / ON) KVMem 少 1.9 / 2.7 GiB KVMem 多 4.5 / 5.0 GiB KVMem 快 ~35% KVMem 快 ~60–90% 原文的 Full-KV 對照(128K):MTP OFF 21,168 MiB、MTP ON 23,008 MiB;
本機 Full-KV 為 20,667 / 22,478 MiB —— 兩者相當吻合(差 2.4%),
可見 KVMem 的 VRAM 節省在兩個環境下是一致的(約 2–3 GiB @128K)。這裡有一個原文沒強調、但很實際的發現
KVMem 不只省 VRAM,還明顯更快。 原因很直接:KVMem 只讓 ~48K token 的
active working set 進 GPU,attention 就只在那個範圍上算;Full-KV 則要在
全部 131K token 上算。所以本機量到 KVMem 的 prefill 快約 35%、decode 快約 60%。容量上的差距更關鍵:
Context KVMem VRAM Full-KV(估計/原文實測) 128K 18,289–19,808 MiB 20,667 MiB(本機實測) 512K 19,195 MiB 依 128K 線性外推約 30–35 GiB → 24GB 卡放不下 也就是說,512K 這件事在原生的 Full-KV 路徑上根本無法成立,這才是 KVMem 的核心價值。
結論
- KVMem 可用且值得用:單張 24GB 7900 XTX 跑通 523,214-token 邏輯上下文,VRAM 僅 18.2–19.8 GiB,速度沒有崩塌(decode 19.5–46.8 tok/s)。原文的核心結論在本機完整複現。
- 最有價值的不是速度,是容量:4 倍上下文、VRAM 幾乎不成長。代價轉移到 Host RAM —— 512K 需要約 20–22 GB 主機 RSS。本機只有 46 GiB,512K 已接近上限(可用 RAM 最低剩 7.1 GiB);原文的 64 GB 餘裕明顯更好。
- KVMem 同時比 Full-KV 快(原文未強調):128K 下 prefill 快 ~35%、decode 快 ~60–90%,因為 attention 只在 ~48K 的 active working set 上計算,而非全部 131K。Full-KV 在 128K 已吃掉 20.7/22.5 GiB,512K 在 24GB 卡上根本無法成立。
- MTP 在超長上下文要算 E2E 帳:本機 MTP ON 對 decode 提升很大(+78~134%),但 TTFT 在 512K 反而多 183 s,與原文結論方向一致。KVMem 與 MTP 可正常疊加。
- 多卡機器要注意:只編譯一個 gfx target 而讓另一個架構的卡保持可見,會導致 HIP GPF 崩潰(本機 gfx1201 + gfx1100);
ROCR_VISIBLE_DEVICES或雙 target 編譯可解。原文的單卡環境不會踩到。 - Recall 的關鍵變數是「GPU working set 覆蓋率」,不是語料大小:256K 可 20/20(100%),384K 掉到 17/20(85%),512K 只剩 10/20(50%)——平滑衰退,不是斷崖。而把
--kvmem-budget從 32768 提到 98304:384K 回到 19/20(95%)、512K 回到 16/20(80%)。另外 retrieval query 必須是「最後一個 user turn」,把長文與問題塞在同一個 user message 會讓 query 變成整段長文,recall 直接掉到 40%。這三點是使用上最容易踩、也最好修的坑。 - 散熱是硬限制:本機 7900 XTX 在滿載時 junction 達 106–107 °C、風扇已 84%、sclk 2519/2634 MHz、功耗僅 179/291 W,明顯已在節流區。這解釋了本機數據普遍低原文 5–28% 且變動大。
實務建議
PROFILE CTX budget reserve Recall 實測 VRAM 峰值 Host RSS 用途 day131072 32768 16384 (62K/256K 都 100%) 19.8 GB 7.2 GB 日常 native262144 32768 16384 20/20(100%) 18.9 GB 12.7 GB 要準、decode 最快 long393216 98304 8192 19/20(95%) 21.3 GB 18.4 GB 長上下文最佳平衡 max524288 98304 8192 16/20(80%) 21.5 GB 23.3 GB 真的需要 512K 時 - 要 recall 準:
PROFILE=long(95%)或native(100%);並把問題放在獨立的 user turn,不要把問題接在超長文件後面同一個 message。 - 要跑 512K:至少先確認散熱(改善風道/機殼風扇),並關掉其他吃 RAM 的服務;46 GiB RAM 是緊繃的。
- 長 session Agent:KVMem 的前綴快取實測有效(512K 下
cache_n=519195,每輪只需 prefill ~500 token),這才是它最實用的場景。
重現指令
# 1) 取得與編譯 cd kvmem-llama.cpp ROCM_PATH=/opt/rocm python3 scripts/build-rocm.py --linux --gpu-targets gfx1100 --jobs 16 # 2) 只暴露 7900 XTX(務必,否則 HIP GPF) export ROCR_VISIBLE_DEVICES=1 # 3) 啟動 512K 服務 ./build-hip-linux/bin/llama-kvmem-server \ -m Qwen3.8-27B-UD-Q4_K_M.gguf \ --device ROCm0 -ngl 99 --load-mode none \ -c 524288 -b 2048 -ub 512 -t 6 --flash-attn on \ --kvmem --kvmem-budget 32768 --kvmem-gen-reserve 16384 \ --kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \ --no-ui # 4) 量測(本報告使用的 harness) python3 bench/ctx_bench.py --binary kvmem-llama.cpp/build-hip-linux/bin/llama-kvmem-server \ --model Qwen3.8-27B-UD-Q4_K_M.gguf \ --out results/x.json --ctx 524288 --target-prompt-tokens 523264 --mtp on -
-
KVMem 在 RX 7900 XTX 24GB 上的實測報告
依 lcz.me/topic/1961(《7900 XTX 的可能性探索|单卡篇(二):KVMem 是个好东西》)的測試口徑,在本機復現並實測。
測試日期:2026-09-29
摘要
- KVMem 成功安裝並以 gfx1100 HIP 編譯完成,實測單張 7900 XTX 24GB 跑通 523,214-token prompt(完整 Prefill → Decode → 正常輸出),邏輯上下文 512K。
- VRAM 峰值僅 17.4–19.8 GiB,與原文一致;上下文從 128K 擴到 512K(4 倍),VRAM 幾乎不成長(代價轉到 Host RAM,512K 需約 20–22 GB RSS)。
- KVMem 不只省 VRAM,也比 Full-KV 快:128K 下 prefill 快 ~35%、decode 快 ~60–90%;Full-KV 在 128K 已吃掉 22,478 MiB(MTP ON),512K 在 24GB 卡上不可能。
- 本機數字整體低於原文約 5–28%,已定位原因:本機 7900 XTX 嚴重熱節流(junction 實測 106–107 °C、風扇已 84%、sclk 僅 2519/2634 MHz、功耗僅 179/291 W)。
- Recall 一開始是本機與原文最大的分歧(後來解決了):62K / 256K 都可 20/20(100%),但 519K 只有 10/20(50%)(原文 90%)。找出兩個關鍵:retrieval query 必須來自「最後一個 user turn」,以及加大
--kvmem-budget能直接把 512K recall 拉回 80%。
測試環境
項目 本機 原文 GPU RX 7900 XTX 24GB(gfx1100),另有 R9700 32GB(gfx1201) RX 7900 XTX 24GB ×1 CPU Intel Xeon E5-2696 v3(18C/36T, 2.3 GHz) AMD Ryzen 5 9600X 系統記憶體 46 GiB 64 GB ROCm 7.2.4 7.2.3 OS / kernel Ubuntu 24.04.4 / 7.0.0-34 Linux 模型 Qwen3.8-27B-UD-Q4_K_M.gguf(16 GB, Unsloth,nextn_predict_layers=1)Qwen3.8-27B Q4_K_M 原生 context 262,144 262,144
安裝與編譯
來源與版本
項目 值 Repo https://github.com/kvmem/kvmem-llama.cpp分支 rocm-beta(HEAD1c4eef7)llama.cpp pin submodule b81c99b(2026-09-02)Patch patches/llama-kvmem-current.patch→ 38 個檔案編譯指令
cd kvmem-llama.cpp ROCM_PATH=/opt/rocm python3 scripts/build-rocm.py --linux --gpu-targets gfx1100 --jobs 16 # → build-hip-linux/bin/llama-kvmem-server共 600 個建置目標、0 錯誤。產出
llama-kvmem-server、llama-kvmem-cli、llama-tokenize等。
踩雷與修復:HIP general protection fault(本機特有)
症狀
以
--device ROCm1(7900 XTX)啟動後,第一個請求必崩:traps: llama-kvmem-ser general protection fault ip:... in libamdhip64.so.7.2.70204 exit code 139伺服器日誌沒有任何錯誤訊息。
定位
AMD_LOG_LEVEL=3的 HIP API trace 給出真正原因:hipLaunchKernel ( ... ) Forcing SPIRV: false :1:hip_fatbin.cpp:687: No compatible code objects found for: gfx1201本機有兩張 AMD 卡,而這次只編譯了
gfx1100。llama.cpp 的 HIP backend 在初始化時會列舉所有可見裝置,某些 kernel 被下到 gfx1201(R9700),該架構沒有對應 code object → HIP 在 fatbin 查找失敗時不回報錯誤而是直接 GPF。這正是原文「單卡 7900 XTX」環境不會踩到的地雷。
解法
export ROCR_VISIBLE_DEVICES=1 # 只暴露 7900 XTX(gfx1100 為 device 0) # 之後用 --device ROCm0驗證:
ggml_cuda_init: found 1 ROCm devices (Total VRAM: 24560 MiB): Device 0: Radeon RX 7900 XTX, gfx1100 (0x1100), ... VRAM: 24560 MiB加上後立即恢復正常。其他可行做法:編譯時帶
--gpu-targets gfx1100,gfx1201(兩個 code object 都編進去),或實體只留一張卡。
長上下文實測結果(主矩陣)
測試口徑
llama-kvmem-server -m Qwen3.8-27B-UD-Q4_K_M.gguf --device ROCm0 -ngl 99 --load-mode none \ -c <ctx> -b 2048 -ub 512 -t 6 --flash-attn on \ --kvmem --kvmem-budget 32768 --kvmem-gen-reserve 16384 \ --kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \ [--spec-type draft-mtp --spec-draft-n-max 2 --spec-kv-dtype f16 --kvmem-mtp-state replay] # MTP ON- prompt 長度以
llama-tokenize精確擬合(誤差 ≤ 128 token),非字元估算。 - Decode 一律取 512 個輸出 token 的完整樣本(非短樣本)。
- VRAM = 全卡
mem_info_vram_used峰值;Host RSS = 伺服器行程 VmRSS 峰值。
實測表
Context 標稱 實際 Prompt MTP Prefill (tok/s) Decode (tok/s) TTFT (s) VRAM 峰值 (MiB) Host RSS 峰值 (MiB) 131,072 128K 130,072 OFF 402.37 19.58 324.8 18,757 6,415 131,072 128K 130,072 ON 442.56 45.90 295.3 19,808 7,205 262,144 256K 261,169 OFF 463.59 25.64 565.6 18,804 10,848 262,144 256K 261,169 ON 428.62 46.83 611.4 19,430 12,146 524,288 512K 523,214 OFF 386.33 19.51 1,358.5 18,289 19,845 524,288 512K 523,214 ON 340.57 34.74 1,541.4 19,195 22,021 6/6 全部成功。512K 一檔完成 523,214-token prompt 的完整 Prefill → Decode → 正常輸出(輸出 512 token),非僅「服務能啟動」。
與原文逐項對照
Context MTP Prefill 本機 / 原文 Decode 本機 / 原文 TTFT 本機 / 原文 (s) 128K OFF 402.4 / 557.6(−27.8%) 19.6 / 27.0(−27.4%) 324.8 / 235.0 128K ON 442.6 / 533.9(−17.1%) 45.9 / 36.6(+25.4%) 295.3 / 246.0 256K OFF 463.6 / 532.6(−13.0%) 25.6 / 26.9(−4.8%) 565.6 / 493.0 256K ON 428.6 / 511.7(−16.2%) 46.8 / 36.4(+28.7%) 611.4 / 513.0 512K OFF 386.3 / 520.3(−25.8%) 19.5 / 26.9(−27.3%) 1,358.5 / 1,009.0 512K ON 340.6 / 500.3(−31.9%) 34.7 / 39.8(−12.7%) 1,541.4 / 1,049.0 最關鍵的一點:VRAM 不隨 Context 成長
Context 邏輯 Context 倍數 VRAM 峰值 (MiB) 128K 1× 18,757 256K 2× 18,804 512K 4× 18,289 邏輯上下文放大 4 倍,VRAM 峰值幾乎不變(甚至略降),穩定落在 18–19.8 GiB。這正是 KVMem 的核心價值:GPU 只維持約 32K active KV working set,超出的歷史 KV 落在 Host RAM(RSS 由 6.4 GB 成長到 19.8/22.0 GB)。原文第 5 節的結論在本機完全複現。
為什麼本機數字偏低:熱節流
原文機器(Ryzen 9600X + B850 平台)在同樣 24GB 卡上明顯更快。本機在 512K 滿載時實測:
指標 實測值 說明 Junction 溫度 106–107 °C RDNA3 節流點約 110 °C Edge / Memory 62–63 °C / 70 °C 風扇 2,467 RPM(84%) 已接近上限 sclk 2,519 MHz(上限 2,634 MHz) 未跑滿 功耗 179 W / 291 W 非功耗限制,是溫度限制 同一張卡在冷機(junction 52 °C)起跑時 512K prefill 可達 601 tok/s,隨著溫度爬升一路掉到 344 tok/s,整段平均 340–386 tok/s。這解釋了:
- 本機 prefill 普遍低於原文;
- 同一設定不同次量測變動可達 ±10%(例如 128K MTP OFF 在背景編譯時 402 tok/s、乾淨重測 437 tok/s);
- MTP ON 的超長上下文檔位掉幅最大(512K ON 僅 340.6 tok/s)。
這是本機散熱條件問題(機殼風道/風扇曲線),不是 KVMem 或 ROCm 的問題。原文環境應未觸發節流。
Recall 測試(Needle-in-a-Haystack)
方法:在長文中等距埋入 20 個互不相關的 6 位數字 needle(
NOTE: the reference code for NEEDLE-xx is CCCCCC.),
在文末逐一提問並精確比對 6 位數字。上下文與 GPU budget 可調。關鍵發現:retrieval query 的「請求結構」才是決定性因素
伺服器是用
find_last_user_role_block()從 最後一個 user 訊息 取出 retrieval query
(tools/llama-kvmem-server.cpp:1012)。因此:- 若把 整篇長文 + 問題塞在同一個 user message,query 就變成整篇長文,retrieval 形同亂選;
- 必須把長文放在前一個 user turn,問題單獨當最後一個 user turn,query 才等於真正的問題。
在 62K context 下把 GPU budget 壓到 8192(覆蓋率僅 ~13%),兩種結構的差距立刻暴露:
請求結構 GPU budget Context Recall A:長文+問題同一個 user message 32768 62K 19/20(95%) B:問題單獨為最後 user turn 32768 62K 20/20(100%) A:長文+問題同一個 user message 8192 62K 11/20(55%) B:問題單獨為最後 user turn 8192 62K 20/20(100%) 解讀:budget 大(32768)時 485 個 block 有 256 個留在 GPU(覆蓋率 53%),
即使 retrieval 很爛 A 也有 95%;把 budget 壓到 8192(覆蓋率 13%)後,
A 掉到 55% 而 B 仍是 100% —— 這證明 B 的 retrieval 是精準的,A 的不是。512K 實測
請求結構 Prompt tokens Recall 備註 A:長文+問題同一個 user message 519,198 8/20(40%) query 變成整篇長文 B:問題單獨為最後 user turn 519,195 10/20(50%) query 正確,但語料放大到 519K 後仍退化 觀察:答錯時模型回傳的幾乎都是另一顆 needle 的號碼(如問 NEEDLE-06 答 567730 = NEEDLE-10 的值),
而不是隨機亂答 —— 表示 needle 的 block 有被取回,但取回的是錯的那一顆。
所有 needle 都以同一句型(...reference code for NEEDLE-xx is ...)書寫,彼此高度相似,
在大語料下 retrieval 的排序鑑別力會下降。與原文對照
來源 Context Recall 原文 KVMem ~520K 18/20(90%) 原文 SGLang / NInfer ~520K 100% 本機 KVMem(62K / budget 8192 / 結構 B) 62K 20/20(100%) 本機 KVMem(512K / budget 32768 / 結構 B) 519K 10/20(50%) 【重要】recall 的關鍵變數是「GPU working set 覆蓋率」,不是語料大小
先前 512K 只拿到 50%,一度以為是大語料下的硬限制。後續在 256K / 384K / 512K
三個檔位(其餘參數完全相同:reserve 固定、MTP on、multiturn、同一批 20 顆 needle)
實測後,可看出規律是覆蓋率,而且衰退是平滑的,不是斷崖:Context budget 候選 blocks 取回 blocks 覆蓋率 Recall VRAM 峰值 Host RSS 峰值 62K 8192 484 64 13% 20/20(結構 B) 17,085 — 256K 32768 2,024 256 12.6% 20/20(100%) 18,865 12,695 384K 32768 3,072 256 8.3% 17/20(85%) 18,857 18,261 384K 98304 3,072 768 25% 19/20(95%) 21,291 18,392 512K 32768 4,056 256 6.3% 10/20(50%) 18,289 19,845 512K 98304 4,056 768 19% 16/20(80%) 21,507 23,304 兩個結論:
- 同一個語料,加大
--kvmem-budget就能把 recall 拉回來:512K 由 50% → 80%,
384K 由 85% → 95%。這是本次最實用的調校結論 —— 要保準確度,該調的是 budget,
不是把 context 開更大。 - 384K + budget 98304 是本機長上下文的最佳平衡點:recall 95%、VRAM 21.3 GiB、
Host RSS 只 18.4 GB(ComfyUI 可以不用關),比 512K 那組(80% / 23.3 GB)明顯划算。
MTP 接受率與效益
KVMem 的 server 不輸出 MTP 接受率統計,因此改用
llama-kvmem-cli
以同一種生成任務(編號清單,512 輸出 token)量測。設定 Decode (tok/s) 相對提升 MTP OFF 29.41 — MTP ON ( --spec-draft-n-max 2, F16 draft KV)50.82 +72.8% 伺服器端 MTP 效益(主矩陣)
Context MTP OFF MTP ON Decode 提升 TTFT 變化 128K 19.58 45.90 +134% −29.5 s 256K 25.64 46.83 +83% +45.8 s 512K 19.51 34.74 +78% +182.9 s 本機的 MTP 增益比原文(+35.6~+48.3%)更大,原因是測試任務是高度可預測的編號清單,
接受率偏高。原文的結論方向一致:KVMem 解決容量、MTP 解決速度,兩者可疊加,
但超長 prompt + 短輸出時要注意 TTFT 變差(512K 時 TTFT 多 183 s)。
Full-KV 對照(
--no-kvmem)以相同模型、相同 prompt(130,072 token)、相同 KV dtype(q8_0)、相同 FA / batch / threads 設定,
只把 KVMem 關掉(--no-kvmem,即傳統 Full-KV 全部常駐 GPU):設定 @128K VRAM 峰值 (MiB) Host RSS 峰值 (MiB) Prefill (tok/s) Decode (tok/s) KVMem(budget 32768)MTP OFF 18,757 6,415 402–437 19.6–21.2 Full-KV( --no-kvmem)MTP OFF20,667 1,895 301.8 12.7 KVMem MTP ON 19,808 7,205 424–443 40.7–45.9 Full-KV MTP ON 22,478 2,180 288.8 23.9 差異(MTP OFF / ON) KVMem 少 1.9 / 2.7 GiB KVMem 多 4.5 / 5.0 GiB KVMem 快 ~35% KVMem 快 ~60–90% 原文的 Full-KV 對照(128K):MTP OFF 21,168 MiB、MTP ON 23,008 MiB;
本機 Full-KV 為 20,667 / 22,478 MiB —— 兩者相當吻合(差 2.4%),
可見 KVMem 的 VRAM 節省在兩個環境下是一致的(約 2–3 GiB @128K)。這裡有一個原文沒強調、但很實際的發現
KVMem 不只省 VRAM,還明顯更快。 原因很直接:KVMem 只讓 ~48K token 的
active working set 進 GPU,attention 就只在那個範圍上算;Full-KV 則要在
全部 131K token 上算。所以本機量到 KVMem 的 prefill 快約 35%、decode 快約 60%。容量上的差距更關鍵:
Context KVMem VRAM Full-KV(估計/原文實測) 128K 18,289–19,808 MiB 20,667 MiB(本機實測) 512K 19,195 MiB 依 128K 線性外推約 30–35 GiB → 24GB 卡放不下 也就是說,512K 這件事在原生的 Full-KV 路徑上根本無法成立,這才是 KVMem 的核心價值。
結論
- KVMem 可用且值得用:單張 24GB 7900 XTX 跑通 523,214-token 邏輯上下文,VRAM 僅 18.2–19.8 GiB,速度沒有崩塌(decode 19.5–46.8 tok/s)。原文的核心結論在本機完整複現。
- 最有價值的不是速度,是容量:4 倍上下文、VRAM 幾乎不成長。代價轉移到 Host RAM —— 512K 需要約 20–22 GB 主機 RSS。本機只有 46 GiB,512K 已接近上限(可用 RAM 最低剩 7.1 GiB);原文的 64 GB 餘裕明顯更好。
- KVMem 同時比 Full-KV 快(原文未強調):128K 下 prefill 快 ~35%、decode 快 ~60–90%,因為 attention 只在 ~48K 的 active working set 上計算,而非全部 131K。Full-KV 在 128K 已吃掉 20.7/22.5 GiB,512K 在 24GB 卡上根本無法成立。
- MTP 在超長上下文要算 E2E 帳:本機 MTP ON 對 decode 提升很大(+78~134%),但 TTFT 在 512K 反而多 183 s,與原文結論方向一致。KVMem 與 MTP 可正常疊加。
- 多卡機器要注意:只編譯一個 gfx target 而讓另一個架構的卡保持可見,會導致 HIP GPF 崩潰(本機 gfx1201 + gfx1100);
ROCR_VISIBLE_DEVICES或雙 target 編譯可解。原文的單卡環境不會踩到。 - Recall 的關鍵變數是「GPU working set 覆蓋率」,不是語料大小:256K 可 20/20(100%),384K 掉到 17/20(85%),512K 只剩 10/20(50%)——平滑衰退,不是斷崖。而把
--kvmem-budget從 32768 提到 98304:384K 回到 19/20(95%)、512K 回到 16/20(80%)。另外 retrieval query 必須是「最後一個 user turn」,把長文與問題塞在同一個 user message 會讓 query 變成整段長文,recall 直接掉到 40%。這三點是使用上最容易踩、也最好修的坑。 - 散熱是硬限制:本機 7900 XTX 在滿載時 junction 達 106–107 °C、風扇已 84%、sclk 2519/2634 MHz、功耗僅 179/291 W,明顯已在節流區。這解釋了本機數據普遍低原文 5–28% 且變動大。
實務建議
PROFILE CTX budget reserve Recall 實測 VRAM 峰值 Host RSS 用途 day131072 32768 16384 (62K/256K 都 100%) 19.8 GB 7.2 GB 日常 native262144 32768 16384 20/20(100%) 18.9 GB 12.7 GB 要準、decode 最快 long393216 98304 8192 19/20(95%) 21.3 GB 18.4 GB 長上下文最佳平衡 max524288 98304 8192 16/20(80%) 21.5 GB 23.3 GB 真的需要 512K 時 - 要 recall 準:
PROFILE=long(95%)或native(100%);並把問題放在獨立的 user turn,不要把問題接在超長文件後面同一個 message。 - 要跑 512K:至少先確認散熱(改善風道/機殼風扇),並關掉其他吃 RAM 的服務;46 GiB RAM 是緊繃的。
- 長 session Agent:KVMem 的前綴快取實測有效(512K 下
cache_n=519195,每輪只需 prefill ~500 token),這才是它最實用的場景。
重現指令
# 1) 取得與編譯 cd kvmem-llama.cpp ROCM_PATH=/opt/rocm python3 scripts/build-rocm.py --linux --gpu-targets gfx1100 --jobs 16 # 2) 只暴露 7900 XTX(務必,否則 HIP GPF) export ROCR_VISIBLE_DEVICES=1 # 3) 啟動 512K 服務 ./build-hip-linux/bin/llama-kvmem-server \ -m Qwen3.8-27B-UD-Q4_K_M.gguf \ --device ROCm0 -ngl 99 --load-mode none \ -c 524288 -b 2048 -ub 512 -t 6 --flash-attn on \ --kvmem --kvmem-budget 32768 --kvmem-gen-reserve 16384 \ --kvmem-block-tokens 128 --kvmem-query-policy user --kv-dtype q8_0 \ --no-ui # 4) 量測(本報告使用的 harness) python3 bench/ctx_bench.py --binary kvmem-llama.cpp/build-hip-linux/bin/llama-kvmem-server \ --model Qwen3.8-27B-UD-Q4_K_M.gguf \ --out results/x.json --ctx 524288 --target-prompt-tokens 523264 --mtp on -
-
-
,为什么不单独发一个帖子呢?
,拉低了本论坛众大佬的身价你这个坛主要承担主要责任哈。