跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 浅色
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • 深色
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(LCZ-Blue)
  • 不使用皮肤
  • LCZ-Green
  • LCZ-Blue
  • LCZ-Black
折叠
品牌标识

抡锤者

首页 版块 标签
硬件
装备秀
AI 广场
  1. 主页
  2. 版块
  3. AI Agent
  4. 7900 XTX 的可能性探索|单卡篇(三):强强联合还是缝合怪?— KVMem × daniel-mtp,快和大可以同时要

7900 XTX 的可能性探索|单卡篇(三):强强联合还是缝合怪?— KVMem × daniel-mtp,快和大可以同时要

已定时 已固定 已锁定 已移动 AI Agent
7900xtxqwen-27brocm
19 帖子 8 发布者 740 浏览 1 关注中
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • 张光璞张
    张光璞张
    张光璞
    技术大牛 劳动模范
    编写于 最后由 编辑
    #10

    单卡都这么强的话,双卡不是飞起?

    Ben LeeB 1 条回复 最后回复
    0
    • 张光璞张 张光璞

      单卡都这么强的话,双卡不是飞起?

      Ben LeeB
      Ben LeeB
      Ben Lee
      超凡大师
      编写于 最后由 编辑
      #11

      @张光璞 单卡还有更亮眼的,等我发第四篇帖子。这个系列的第五篇我准备发双卡并发,目前测试其实还不如单卡,不过也算抛砖引玉。

      1 条回复 最后回复
      0
      • 蕭小小蕭
        蕭小小蕭
        蕭小小
        编写于 最后由 编辑
        #12

        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(HEAD 1c4eef7)
        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。這解釋了:

        1. 本機 prefill 普遍低於原文;
        2. 同一設定不同次量測變動可達 ±10%(例如 128K MTP OFF 在背景編譯時 402 tok/s、乾淨重測 437 tok/s);
        3. 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

        兩個結論:

        1. 同一個語料,加大 --kvmem-budget 就能把 recall 拉回來:512K 由 50% → 80%,
          384K 由 85% → 95%。這是本次最實用的調校結論 —— 要保準確度,該調的是 budget,
          不是把 context 開更大
          。
        2. 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 OFF 20,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 的核心價值。


        結論

        1. KVMem 可用且值得用:單張 24GB 7900 XTX 跑通 523,214-token 邏輯上下文,VRAM 僅 18.2–19.8 GiB,速度沒有崩塌(decode 19.5–46.8 tok/s)。原文的核心結論在本機完整複現。
        2. 最有價值的不是速度,是容量:4 倍上下文、VRAM 幾乎不成長。代價轉移到 Host RAM —— 512K 需要約 20–22 GB 主機 RSS。本機只有 46 GiB,512K 已接近上限(可用 RAM 最低剩 7.1 GiB);原文的 64 GB 餘裕明顯更好。
        3. 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 卡上根本無法成立。
        4. MTP 在超長上下文要算 E2E 帳:本機 MTP ON 對 decode 提升很大(+78~134%),但 TTFT 在 512K 反而多 183 s,與原文結論方向一致。KVMem 與 MTP 可正常疊加。
        5. 多卡機器要注意:只編譯一個 gfx target 而讓另一個架構的卡保持可見,會導致 HIP GPF 崩潰(本機 gfx1201 + gfx1100);ROCR_VISIBLE_DEVICES 或雙 target 編譯可解。原文的單卡環境不會踩到。
        6. 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%。這三點是使用上最容易踩、也最好修的坑。
        7. 散熱是硬限制:本機 7900 XTX 在滿載時 junction 達 106–107 °C、風扇已 84%、sclk 2519/2634 MHz、功耗僅 179/291 W,明顯已在節流區。這解釋了本機數據普遍低原文 5–28% 且變動大。

        實務建議

        PROFILE CTX budget reserve Recall 實測 VRAM 峰值 Host RSS 用途
        day 131072 32768 16384 (62K/256K 都 100%) 19.8 GB 7.2 GB 日常
        native 262144 32768 16384 20/20(100%) 18.9 GB 12.7 GB 要準、decode 最快
        long 393216 98304 8192 19/20(95%) 21.3 GB 18.4 GB 長上下文最佳平衡
        max 524288 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
        
        johnnybegoodJ Ben LeeB 2 条回复 最后回复
        1
        • Ben LeeB Ben Lee

          @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 秒,这就等于是卡了六分多钟。除非是晚上休息让模型自己跑任务,否则一般情况还是很难忍受经常要卡几分钟的情况(我略微夸张的描述哈,真实使用还好)

          dardeaw fengD
          dardeaw fengD
          dardeaw feng
          德高望重 劳动模范
          编写于 最后由 编辑
          #13

          @Ben-Lee
          你這命中率偏低,因為llama.cpp的前綴你要深挖優化,弄到增量以外都能命中,
          冷啟動還好,把顯存的ctx弄到ssd去吧,我以前玩llama.cpp都這樣幹,對話id跟模型當key就好,但要客製處理前綴的時間戳記,KVMem底子就是llama.cpp一定可以
          Recall 先天就是中段(40-60% 深度)最弱:文件正中間的資訊召回率比頭尾差,那就是產生幻覺,但你論述上"不編程沒影響"有個矛盾....不編程的話根本不需要太大的KV呀?那KVMem存在的意義就很薄弱了。建議上git+codegraph給harness做輔助讓他不用看整段代碼,可以彌補長文本的中段弱點。

          1 条回复 最后回复
          0
          • 蕭小小蕭 蕭小小

            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(HEAD 1c4eef7)
            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。這解釋了:

            1. 本機 prefill 普遍低於原文;
            2. 同一設定不同次量測變動可達 ±10%(例如 128K MTP OFF 在背景編譯時 402 tok/s、乾淨重測 437 tok/s);
            3. 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

            兩個結論:

            1. 同一個語料,加大 --kvmem-budget 就能把 recall 拉回來:512K 由 50% → 80%,
              384K 由 85% → 95%。這是本次最實用的調校結論 —— 要保準確度,該調的是 budget,
              不是把 context 開更大
              。
            2. 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 OFF 20,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 的核心價值。


            結論

            1. KVMem 可用且值得用:單張 24GB 7900 XTX 跑通 523,214-token 邏輯上下文,VRAM 僅 18.2–19.8 GiB,速度沒有崩塌(decode 19.5–46.8 tok/s)。原文的核心結論在本機完整複現。
            2. 最有價值的不是速度,是容量:4 倍上下文、VRAM 幾乎不成長。代價轉移到 Host RAM —— 512K 需要約 20–22 GB 主機 RSS。本機只有 46 GiB,512K 已接近上限(可用 RAM 最低剩 7.1 GiB);原文的 64 GB 餘裕明顯更好。
            3. 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 卡上根本無法成立。
            4. MTP 在超長上下文要算 E2E 帳:本機 MTP ON 對 decode 提升很大(+78~134%),但 TTFT 在 512K 反而多 183 s,與原文結論方向一致。KVMem 與 MTP 可正常疊加。
            5. 多卡機器要注意:只編譯一個 gfx target 而讓另一個架構的卡保持可見,會導致 HIP GPF 崩潰(本機 gfx1201 + gfx1100);ROCR_VISIBLE_DEVICES 或雙 target 編譯可解。原文的單卡環境不會踩到。
            6. 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%。這三點是使用上最容易踩、也最好修的坑。
            7. 散熱是硬限制:本機 7900 XTX 在滿載時 junction 達 106–107 °C、風扇已 84%、sclk 2519/2634 MHz、功耗僅 179/291 W,明顯已在節流區。這解釋了本機數據普遍低原文 5–28% 且變動大。

            實務建議

            PROFILE CTX budget reserve Recall 實測 VRAM 峰值 Host RSS 用途
            day 131072 32768 16384 (62K/256K 都 100%) 19.8 GB 7.2 GB 日常
            native 262144 32768 16384 20/20(100%) 18.9 GB 12.7 GB 要準、decode 最快
            long 393216 98304 8192 19/20(95%) 21.3 GB 18.4 GB 長上下文最佳平衡
            max 524288 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
            
            johnnybegoodJ
            johnnybegoodJ
            johnnybegood
            超凡大师
            编写于 最后由 编辑
            #14

            @蕭小小 107度。。。要是我的话我得疯掉!,我觉得再低30度才正常吧!!

            1 条回复 最后回复
            0
            • fcmeF fcme

              @Ben-Lee
              Hermes的基础开销太大了,换dsh这种轻量的Agent用本地模型也没啥便秘感了。dsh就是严格的append型为了缓存利用效率。

              Ben LeeB
              Ben LeeB
              Ben Lee
              超凡大师
              编写于 最后由 编辑
              #15

              @fcme 谢谢提醒,这周已经开始部署尝试DSH,目前感觉非常良好。

              1 条回复 最后回复
              1
              • 蕭小小蕭 蕭小小

                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(HEAD 1c4eef7)
                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。這解釋了:

                1. 本機 prefill 普遍低於原文;
                2. 同一設定不同次量測變動可達 ±10%(例如 128K MTP OFF 在背景編譯時 402 tok/s、乾淨重測 437 tok/s);
                3. 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

                兩個結論:

                1. 同一個語料,加大 --kvmem-budget 就能把 recall 拉回來:512K 由 50% → 80%,
                  384K 由 85% → 95%。這是本次最實用的調校結論 —— 要保準確度,該調的是 budget,
                  不是把 context 開更大
                  。
                2. 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 OFF 20,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 的核心價值。


                結論

                1. KVMem 可用且值得用:單張 24GB 7900 XTX 跑通 523,214-token 邏輯上下文,VRAM 僅 18.2–19.8 GiB,速度沒有崩塌(decode 19.5–46.8 tok/s)。原文的核心結論在本機完整複現。
                2. 最有價值的不是速度,是容量:4 倍上下文、VRAM 幾乎不成長。代價轉移到 Host RAM —— 512K 需要約 20–22 GB 主機 RSS。本機只有 46 GiB,512K 已接近上限(可用 RAM 最低剩 7.1 GiB);原文的 64 GB 餘裕明顯更好。
                3. 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 卡上根本無法成立。
                4. MTP 在超長上下文要算 E2E 帳:本機 MTP ON 對 decode 提升很大(+78~134%),但 TTFT 在 512K 反而多 183 s,與原文結論方向一致。KVMem 與 MTP 可正常疊加。
                5. 多卡機器要注意:只編譯一個 gfx target 而讓另一個架構的卡保持可見,會導致 HIP GPF 崩潰(本機 gfx1201 + gfx1100);ROCR_VISIBLE_DEVICES 或雙 target 編譯可解。原文的單卡環境不會踩到。
                6. 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%。這三點是使用上最容易踩、也最好修的坑。
                7. 散熱是硬限制:本機 7900 XTX 在滿載時 junction 達 106–107 °C、風扇已 84%、sclk 2519/2634 MHz、功耗僅 179/291 W,明顯已在節流區。這解釋了本機數據普遍低原文 5–28% 且變動大。

                實務建議

                PROFILE CTX budget reserve Recall 實測 VRAM 峰值 Host RSS 用途
                day 131072 32768 16384 (62K/256K 都 100%) 19.8 GB 7.2 GB 日常
                native 262144 32768 16384 20/20(100%) 18.9 GB 12.7 GB 要準、decode 最快
                long 393216 98304 8192 19/20(95%) 21.3 GB 18.4 GB 長上下文最佳平衡
                max 524288 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
                
                Ben LeeB
                Ben LeeB
                Ben Lee
                超凡大师
                编写于 最后由 编辑
                #16

                @蕭小小 你的复现测试做的这么好👍 ,为什么不单独发一个帖子呢?

                1 条回复 最后回复
                0
                • 蕭小小蕭
                  蕭小小蕭
                  蕭小小
                  编写于 最后由 编辑
                  #17

                  @Ben Lee 多谢,已單獨發帖

                  1 条回复 最后回复
                  0
                  • terryT
                    terryT
                    terry
                    超级版主
                    编写于 最后由 terry 编辑
                    #18

                    讲实话这个帖子质量很高,但是我不能给你再加精了,次数太多,别人以为我们在搞基。而且这篇太小众了。哎哟我草,你都超凡大师了。恭喜!

                    油管:https://www.youtube.com/@抡锤者

                    Ben LeeB 1 条回复 最后回复
                    0
                    • terryT terry

                      讲实话这个帖子质量很高,但是我不能给你再加精了,次数太多,别人以为我们在搞基。而且这篇太小众了。哎哟我草,你都超凡大师了。恭喜!

                      Ben LeeB
                      Ben LeeB
                      Ben Lee
                      超凡大师
                      编写于 最后由 编辑
                      #19

                      @terry 我这厮怎么混上这个头衔的😵‍💫,拉低了本论坛众大佬的身价你这个坛主要承担主要责任哈。

                      1 条回复 最后回复
                      0

                      你好!看起来您对这段对话很感兴趣,但您还没有一个账号。

                      厌倦了每次访问都刷到同样的帖子?您注册账号后,您下次访问时都将自动回到上次浏览的位置,并可选择接收新回复的通知(通过电子邮件或推送通知)。您还可以收藏帖子、为帖子点赞,以此向其他社区成员表达您的感谢。

                      有了你的建议,这篇帖子会更精彩哦 💗

                      注册 登录
                      回复
                      • 在新帖中回复
                      登录后回复
                      • 从旧到新
                      • 从新到旧
                      • 最多赞同


                      • 登录

                      • 登录或注册以进行搜索。
                      • 第一个帖子
                        最后一个帖子
                      0
                      • 版块
                      • 最新
                      • 标签
                      • 热门
                      • 用户
                      • 群组