<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[7900 XTX 的可能性探索｜单卡篇（二）：KVMem 是个好东西—— 7900XTX 24GB 显存实测跑通 512K Context]]></title><description><![CDATA[<p dir="auto">先感谢 KVMem 的作者和贡献者</p>
<p dir="auto">首先一定要特别感谢 KVMem 项目的作者和贡献者。</p>
<p dir="auto">KVMem 是一个很有意思的长上下文 KV 管理方案，由 Di Chai、Leye Wang、Zeshen Su、Zhiguo Xia、Zhihang Yu 等作者开发。</p>
<p dir="auto">项目地址：</p>
<p dir="auto"><a href="https://github.com/kvmem/kvmem-llama.cpp" rel="nofollow ugc">https://github.com/kvmem/kvmem-llama.cpp</a></p>
<p dir="auto">作者相关 Bilibili 介绍视频：</p>
<p dir="auto"><a href="https://www.bilibili.com/video/BV1r2ey6EEh5/" rel="nofollow ugc">https://www.bilibili.com/video/BV1r2ey6EEh5/</a></p>
<p dir="auto">也感谢作者把这套方案和实现公开出来，给消费级显卡探索超长上下文提供了一个很有价值的方向。</p>
<hr />
<h2>1. 为什么我又来折腾 KVMem</h2>
<p dir="auto">最近本地推理的新技术和新玩法层出不穷，我自己最感兴趣的几个方向里，就包括 NInfer、KVMem 和 JEV。</p>
<p dir="auto">之前我已经在 NVIDIA 显卡上测试过 KVMem，对这个方案一直很感兴趣。前两天突然看到项目开始支持 AMD / ROCm，我一下又来劲了，于是连续肝了两天，把单卡 7900 XTX 下的适配、排错和长上下文测试基本完整跑了一遍。</p>
<p dir="auto">下面就是这轮测试的阶段性结果。</p>
<hr />
<h2>2. KVMem 到底解决什么问题？</h2>
<p dir="auto">传统 Full-KV 的问题很直接：</p>
<blockquote>
<p dir="auto"><strong>Context 越长，KV Cache 占用的显存越大。</strong></p>
</blockquote>
<p dir="auto">消费级显卡即使模型权重能放进去，Context 继续往上拉以后，最后很容易撞到显存墙。</p>
<p dir="auto">KVMem 的思路不是要求整个超长历史的 KV 全部长期驻留在 GPU。</p>
<p dir="auto">简单理解：</p>
<ul>
<li>GPU 只维持一个有限大小的 active KV working set</li>
<li>更大的历史状态放到 Host RAM</li>
<li>需要时再进行 retrieval / restore</li>
<li>因此逻辑 Context 可以远远超过传统 Full-KV 能容纳的范围</li>
</ul>
<p dir="auto">所以它解决的核心问题不是：</p>
<blockquote>
<p dir="auto">“怎么让模型本身变快”</p>
</blockquote>
<p dir="auto">而是：</p>
<blockquote>
<p dir="auto"><strong>“怎么用有限的 GPU 显存，维持远大于显存容量本身能承载的上下文。”</strong></p>
</blockquote>
<p dir="auto">众所周知，7900XTX先生威猛但是显存略短，对于24GB的它来说，这个方向非常有吸引力。<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f436.png?v=fe25256ab4a" class="not-responsive emoji emoji-android emoji--dog" style="height:1.4em;width:auto;vertical-align:middle" title="🐶" alt="🐶" /></p>
<hr />
<h2>3. 测试环境、部署方法和参数</h2>
<h3>硬件与环境</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项目</th>
<th>配置</th>
</tr>
</thead>
<tbody>
<tr>
<td>GPU</td>
<td>AMD Radeon RX 7900 XTX 24GB</td>
</tr>
<tr>
<td>GPU 数量</td>
<td>1</td>
</tr>
<tr>
<td>CPU</td>
<td>AMD Ryzen 5 9600X</td>
</tr>
<tr>
<td>主板</td>
<td>GIGABYTE B850 AI TOP AMD AM5 ATX</td>
</tr>
<tr>
<td>系统内存</td>
<td>64GB DDR5</td>
</tr>
<tr>
<td>PCIe</td>
<td>PCIe 4.0 x8（主机安装双卡，本篇仅使用 GPU0 单卡）</td>
</tr>
<tr>
<td>OS</td>
<td>Linux</td>
</tr>
<tr>
<td>ROCm</td>
<td>7.2.3</td>
</tr>
<tr>
<td>Backend</td>
<td>llama.cpp HIP</td>
</tr>
<tr>
<td>Model</td>
<td>Qwen3.8-27B Q4_K_M</td>
</tr>
<tr>
<td>GPU offload</td>
<td>Full GPU offload</td>
</tr>
<tr>
<td>Flash Attention</td>
<td>ON</td>
</tr>
<tr>
<td>KV</td>
<td><code>q8_0</code></td>
</tr>
<tr>
<td>KVMem budget</td>
<td>32K</td>
</tr>
<tr>
<td>MTP</td>
<td>模型自带 nextn head</td>
</tr>
<tr>
<td>GPU arch</td>
<td>gfx1100</td>
</tr>
</tbody>
</table>
<h3>KVMem 版本</h3>
<p dir="auto">这轮测试使用的是 KVMem 官方 AMD / ROCm Beta 分支：</p>
<p dir="auto"><code>rc3-rocm-beta2</code></p>
<p dir="auto">项目地址：</p>
<p dir="auto"><a href="https://github.com/kvmem/kvmem-llama.cpp" rel="nofollow ugc">https://github.com/kvmem/kvmem-llama.cpp</a></p>
<p dir="auto">我没有直接使用通用多架构 build，而是在本机针对 <code>gfx1100</code> 重新编译。</p>
<p dir="auto">主要编译方向：</p>
<ul>
<li>HIP / ROCm</li>
<li><code>gfx1100</code> only</li>
<li>Native build</li>
<li>Ninja 并行编译</li>
<li>针对 RX 7900 XTX 使用本地优化参数</li>
</ul>
<p dir="auto">本轮测试使用的主要编译参数包括：</p>
<p dir="auto"><code>GGML_NATIVE=ON</code></p>
<p dir="auto"><code>GGML_OPENMP=ON</code></p>
<p dir="auto">以及：</p>
<p dir="auto"><code>CMAKE_HIP_FLAGS="-mllvm --amdgpu-unroll-threshold-local=600"</code></p>
<p dir="auto">这样做的目的很简单：</p>
<blockquote>
<p dir="auto">尽量减少和本机 RX 7900 XTX 无关的通用架构开销，把测试环境固定在 <code>gfx1100</code>。</p>
</blockquote>
<h3>推理参数</h3>
<p dir="auto">本轮长上下文测试统一使用：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>参数</th>
<th>设置</th>
</tr>
</thead>
<tbody>
<tr>
<td>GPU</td>
<td>单张 RX 7900 XTX</td>
</tr>
<tr>
<td>Model</td>
<td>Qwen3.8-27B Q4_K_M</td>
</tr>
<tr>
<td>KV</td>
<td><code>q8_0</code></td>
</tr>
<tr>
<td>KVMem budget</td>
<td><code>32768</code></td>
</tr>
<tr>
<td>Flash Attention</td>
<td>ON</td>
</tr>
<tr>
<td>Batch</td>
<td><code>2048</code></td>
</tr>
<tr>
<td>UBatch</td>
<td><code>512</code></td>
</tr>
<tr>
<td>Threads</td>
<td><code>6</code></td>
</tr>
<tr>
<td>Output cap</td>
<td><code>512 tokens</code></td>
</tr>
<tr>
<td>MTP</td>
<td>OFF / ON 两组</td>
</tr>
<tr>
<td>Context</td>
<td>128K / 256K / 512K</td>
</tr>
</tbody>
</table>
<p dir="auto">这里的 <code>32768</code> 不是最大 Context。</p>
<p dir="auto">它表示：</p>
<blockquote>
<p dir="auto"><strong>GPU 侧 KVMem active working set 的预算约为 32K。</strong></p>
</blockquote>
<p dir="auto">真正测试的逻辑 Context 分别为：</p>
<ul>
<li>128K</li>
<li>256K</li>
<li>512K</li>
</ul>
<p dir="auto">也就是说，512K 测试并不是让 512K KV 全部常驻显存，而是：</p>
<blockquote>
<p dir="auto"><strong>用约 32K 的 GPU active KV budget，配合 Host RAM 中更大的历史状态，通过 retrieval / restore 机制维持 512K 逻辑 Context。</strong></p>
</blockquote>
<h3>为什么 KV 继续使用 q8_0</h3>
<p dir="auto">上一篇传统 Full-KV 测试里，我已经对 <code>q8_0</code> 和 <code>q4_0</code> KV 做过对比。</p>
<p dir="auto">在我的机器和这套模型上，两者对 Prefill 性能影响很小。</p>
<p dir="auto">因此这篇为了减少变量，继续统一使用：</p>
<p dir="auto"><code>q8_0 KV</code></p>
<p dir="auto">不再同时展开 q4 KV 测试。</p>
<h3>测试口径</h3>
<p dir="auto">所有 Context 档位都使用实际 tokenizer token 数，不使用字符数估算。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="text-align:right">标称 Context</th>
<th style="text-align:right">Actual Prompt</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">128K</td>
<td style="text-align:right">130,942</td>
</tr>
<tr>
<td style="text-align:right">256K</td>
<td style="text-align:right">261,875</td>
</tr>
<tr>
<td style="text-align:right">512K</td>
<td style="text-align:right">523,744</td>
</tr>
</tbody>
</table>
<p dir="auto">测试要求不是单纯：</p>
<blockquote>
<p dir="auto">“服务能启动”<br />
“ctx-size 能设置成功”<br />
“模型没有立刻 OOM”</p>
</blockquote>
<p dir="auto">而是必须完成：</p>
<blockquote>
<p dir="auto"><strong>完整 Prompt Prefill → 正常进入 Decode → 正常输出</strong></p>
</blockquote>
<p dir="auto">下面直接看完整测试结果。</p>
<hr />
<h2>4. 长上下文完整测试结果</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="text-align:right">Context</th>
<th style="text-align:right">Actual Prompt</th>
<th style="text-align:center">MTP</th>
<th style="text-align:right">Prefill</th>
<th style="text-align:right">Decode</th>
<th style="text-align:right">TTFT</th>
<th style="text-align:right">Acceptance</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">128K</td>
<td style="text-align:right">130,942</td>
<td style="text-align:center">OFF</td>
<td style="text-align:right"><strong>557.63 tok/s</strong></td>
<td style="text-align:right"><strong>26.98 tok/s</strong></td>
<td style="text-align:right">235 s</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td style="text-align:right">128K</td>
<td style="text-align:right">130,942</td>
<td style="text-align:center">ON</td>
<td style="text-align:right"><strong>533.94 tok/s</strong></td>
<td style="text-align:right"><strong>36.59 tok/s</strong></td>
<td style="text-align:right">246 s</td>
<td style="text-align:right">50.8%</td>
</tr>
<tr>
<td style="text-align:right">256K</td>
<td style="text-align:right">261,875</td>
<td style="text-align:center">OFF</td>
<td style="text-align:right"><strong>532.61 tok/s</strong></td>
<td style="text-align:right"><strong>26.94 tok/s</strong></td>
<td style="text-align:right">493 s</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td style="text-align:right">256K</td>
<td style="text-align:right">261,875</td>
<td style="text-align:center">ON</td>
<td style="text-align:right"><strong>511.73 tok/s</strong></td>
<td style="text-align:right"><strong>36.38 tok/s</strong></td>
<td style="text-align:right">513 s</td>
<td style="text-align:right">50.0%</td>
</tr>
<tr>
<td style="text-align:right">512K</td>
<td style="text-align:right">523,744</td>
<td style="text-align:center">OFF</td>
<td style="text-align:right"><strong>520.34 tok/s</strong></td>
<td style="text-align:right"><strong>26.85 tok/s</strong></td>
<td style="text-align:right">1009 s</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td style="text-align:right">512K</td>
<td style="text-align:right">523,744</td>
<td style="text-align:center">ON</td>
<td style="text-align:right"><strong>500.34 tok/s</strong></td>
<td style="text-align:right"><strong>39.81 tok/s</strong></td>
<td style="text-align:right">1049 s</td>
<td style="text-align:right">58.4%</td>
</tr>
</tbody>
</table>
<p dir="auto">其中 512K 档实际完成：</p>
<blockquote>
<p dir="auto"><strong>523,744-token Prompt → 完整 Prefill → 正常进入 Decode</strong></p>
</blockquote>
<p dir="auto">这里不是单纯把 <code>ctx-size</code> 设置成 512K，也不是只完成模型加载，而是真正把超过 52 万 token 的 Prompt 完整跑完并正常生成。</p>
<h3>测试结果图</h3>
<p dir="auto"><img src="https://upload.lcz.me/uploads/02887459-cf91-4e31-ab3e-8577cc8acd9e.png" alt="ChatGPT Image Sep 27, 2026, 01_05_42 AM.png" class="img-markdown  img-fluid" /></p>
<p dir="auto">从表格和图里已经可以比较直观看到：</p>
<ul>
<li>Context 从 128K 一路增加到 512K 后，Prefill throughput 仍然保持在较高水平；</li>
<li>MTP OFF 的 Decode 基本稳定在约 <code>27 tok/s</code>；</li>
<li>MTP ON 后，Decode 提升到约 <code>36～40 tok/s</code>；</li>
<li>512K 实际 Prompt 达到 <strong>523,744 tokens</strong>，整轮测试正常完成。</li>
</ul>
<p dir="auto">后面不再重复展开 Prefill 曲线，重点看 KVMem 真正带来的几个实际变化。</p>
<hr />
<h2>5. VRAM 与 Host RAM：24GB 为什么能跑到 512K</h2>
<p dir="auto">这其实是我认为 KVMem 最核心的价值。</p>
<p dir="auto">在 128K / 256K / 512K 的测试过程中，VRAM Peak 基本维持在：</p>
<p dir="auto"><strong>约 18.2～19.5 GiB</strong></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="text-align:right">Context</th>
<th style="text-align:right">VRAM Peak</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">128K</td>
<td style="text-align:right">约 18～19 GiB</td>
</tr>
<tr>
<td style="text-align:right">256K</td>
<td style="text-align:right">约 18～19 GiB</td>
</tr>
<tr>
<td style="text-align:right">512K</td>
<td style="text-align:right">约 19 GiB</td>
</tr>
</tbody>
</table>
<p dir="auto">逻辑 Context 从 128K 增长到 512K，GPU 显存并没有跟着线性增加。</p>
<p dir="auto">上一篇同一个 <code>Qwen3.8-27B Q4_K_M</code>、<code>q8_0 KV</code> 的传统 Full-KV 测试中，128K 实际 Prompt 为 130,941 tokens：</p>
<ul>
<li>MTP OFF VRAM Peak：<strong>21,168 MiB</strong></li>
<li>MTP ON VRAM Peak：<strong>23,008 MiB</strong></li>
</ul>
<p dir="auto">也就是说，在传统 Full-KV 下，128K 已经开始明显逼近 24GB 显存上限。</p>
<p dir="auto">而 KVMem 并不是把这些 KV “变没了”。</p>
<p dir="auto">更准确地说，它是在做一种资源交换：</p>
<blockquote>
<p dir="auto"><strong>减少 GPU VRAM 中长期驻留的 KV，用 Host RAM 承载更大的历史状态。</strong></p>
</blockquote>
<p dir="auto">GPU 侧只维持有限的 active KV working set，需要时再进行 retrieval / restore。</p>
<p dir="auto">因此：</p>
<blockquote>
<p dir="auto"><strong>更少的 VRAM 压力 <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2194.png?v=fe25256ab4a" class="not-responsive emoji emoji-android emoji--left_right_arrow" style="height:1.4em;width:auto;vertical-align:middle" title="↔" alt="↔" /> 更多的 Host RAM 使用</strong></p>
</blockquote>
<p dir="auto">这台测试机一共只有 <strong>64GB DDR5 系统内存</strong>。</p>
<p dir="auto">所以随着逻辑 Context 继续扩大，GPU VRAM 不再是唯一的容量边界，Host RAM 也会逐渐成为新的限制因素。</p>
<p dir="auto">这里需要特别说明：</p>
<blockquote>
<p dir="auto"><strong>这次测试停在 512K，不代表 KVMem 的最大能力就是 512K。</strong></p>
</blockquote>
<p dir="auto">我没有继续把正式测试推到 1M，主要有两个原因：</p>
<ol>
<li>512K 已经足够验证单张 24GB RX 7900 XTX 上 KVMem 的长上下文扩展能力；</li>
<li>继续向 1M 推进会进一步增加 Host RAM 和整机资源压力，而这台测试机只有 64GB 系统内存，继续追求最大 Context 已经偏离本轮测试重点。</li>
</ol>
<p dir="auto">本文能够严谨确认的是：</p>
<blockquote>
<p dir="auto"><strong>这套配置实际完整验证到了 523,744-token Prompt。</strong></p>
</blockquote>
<p dir="auto">至于 1M 或更高，本轮没有完整验证，因此不做结论。</p>
<p dir="auto">所以 KVMem 解决的首先是：</p>
<blockquote>
<p dir="auto"><strong>Context Capacity。</strong></p>
</blockquote>
<p dir="auto">它不是把 24GB 显存“变成了 48GB”，也不是把 50 万 token 的计算成本变没。</p>
<p dir="auto">它改变的是：</p>
<blockquote>
<p dir="auto"><strong>“全部历史 KV 必须长期驻留在 GPU 显存里”这个前提。</strong></p>
</blockquote>
<hr />
<h2>6. KVMem Budget 到底控制什么？</h2>
<p dir="auto">这一点我觉得有必要单独讲。</p>
<p dir="auto">本文性能测试统一使用：</p>
<p dir="auto"><code>KVMem budget = 32768</code></p>
<p dir="auto">这里的 <code>32768</code> 并不是最大 Context，而是 GPU 侧允许保留的 active KV working set 大小。</p>
<p dir="auto">简单理解：</p>
<blockquote>
<p dir="auto"><strong>Budget 越大，GPU 里同时保留的 KV 越多；Budget 越小，就越依赖 Host RAM 和 retrieval / restore。</strong></p>
</blockquote>
<p dir="auto">所以 KVMem budget 本质上控制的是一个资源平衡：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>KVMem Budget</th>
<th>GPU VRAM</th>
<th>Retrieval 依赖</th>
<th>Recall 潜力</th>
</tr>
</thead>
<tbody>
<tr>
<td>较小</td>
<td>更低</td>
<td>更高</td>
<td>极端场景更容易出现 miss</td>
</tr>
<tr>
<td>较大</td>
<td>更高</td>
<td>更低</td>
<td>通常更有利于 Recall</td>
</tr>
</tbody>
</table>
<p dir="auto">这也是为什么：</p>
<p dir="auto"><code>KVMem budget = 32768</code></p>
<p dir="auto">并不意味着只能跑 32K Context。</p>
<p dir="auto">本轮测试里，GPU active KV budget 固定在约 32K，但实际逻辑 Context 分别跑到了：</p>
<ul>
<li>128K</li>
<li>256K</li>
<li>512K</li>
</ul>
<p dir="auto">也就是说：</p>
<blockquote>
<p dir="auto"><strong>Context 可以继续增长，但 GPU 侧 active KV 的预算基本保持固定。</strong></p>
</blockquote>
<p dir="auto">超出 active budget 的历史状态更多地由 Host RAM 承担，需要时再通过 retrieval / restore 重新带回。</p>
<hr />
<h3>为什么这篇统一使用 32K Budget？</h3>
<p dir="auto">这轮测试的目的不是找“最大 Recall”，而是想回答一个更直接的问题：</p>
<blockquote>
<p dir="auto"><strong>如果把 GPU 侧 active KV 固定在一个比较小的范围内，单张 24GB RX 7900 XTX 到底能把逻辑 Context 推多远？</strong></p>
</blockquote>
<p dir="auto">所以我统一使用：</p>
<p dir="auto"><code>32768</code></p>
<p dir="auto">最终实测：</p>
<blockquote>
<p dir="auto"><strong>32K active KV budget → 523,744-token Prompt 完整跑通</strong></p>
</blockquote>
<p dir="auto">同时 GPU VRAM Peak 基本仍维持在约：</p>
<p dir="auto"><strong>18.2～19.5 GiB</strong></p>
<p dir="auto">这正是 KVMem 最有意思的地方之一。</p>
<hr />
<h3>Budget 不是越小越好</h3>
<p dir="auto">Budget 越小，确实越省 GPU KV 空间，也更有利于把逻辑 Context 往上推。</p>
<p dir="auto">但代价也很明确：</p>
<blockquote>
<p dir="auto"><strong>更依赖 retrieval。</strong></p>
</blockquote>
<p dir="auto">而 retrieval 越频繁、active working set 越小，在极端长上下文场景下，就越有可能暴露 Recall 边界。</p>
<p dir="auto">我们之前的测试也已经观察到：</p>
<blockquote>
<p dir="auto"><strong>提高 active KV budget 后，极端 needle Recall 会改善。</strong></p>
</blockquote>
<p dir="auto">所以实际部署时不能只追求最小 budget。</p>
<p dir="auto">更合理的选择是根据用途做平衡：</p>
<ul>
<li><strong>追求最大 Context / 节省 VRAM</strong>：budget 可以偏小</li>
<li><strong>更重视 Recall</strong>：budget 可以适当增大</li>
<li><strong>系统内存有限</strong>：还要同时考虑 Host RAM 压力</li>
</ul>
<p dir="auto">最终实际上是在四个变量之间找平衡：</p>
<blockquote>
<p dir="auto"><strong>VRAM / Host RAM / Context Capacity / Recall Quality</strong></p>
</blockquote>
<p dir="auto">所以 KVMem 的真正玩法，并不是单纯问：</p>
<blockquote>
<p dir="auto">“最大能跑多少 K？”</p>
</blockquote>
<p dir="auto">而是：</p>
<blockquote>
<p dir="auto"><strong>“在我能接受的显存和内存占用下，需要多大的 active KV budget，才能获得足够可靠的 Recall？”</strong></p>
</blockquote>
<hr />
<h2>7. MTP：可以和 KVMem 叠加，但要看实际 E2E</h2>
<p dir="auto">KVMem 和 MTP 可以正常一起使用。</p>
<p dir="auto">Decode 实测：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="text-align:right">Context</th>
<th style="text-align:right">MTP OFF</th>
<th style="text-align:right">MTP ON</th>
<th style="text-align:right">Decode 提升</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">128K</td>
<td style="text-align:right">26.98 tok/s</td>
<td style="text-align:right">36.59 tok/s</td>
<td style="text-align:right"><strong>+35.6%</strong></td>
</tr>
<tr>
<td style="text-align:right">256K</td>
<td style="text-align:right">26.94 tok/s</td>
<td style="text-align:right">36.38 tok/s</td>
<td style="text-align:right"><strong>+35.0%</strong></td>
</tr>
<tr>
<td style="text-align:right">512K</td>
<td style="text-align:right">26.85 tok/s</td>
<td style="text-align:right">39.81 tok/s</td>
<td style="text-align:right"><strong>+48.3%</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">512K 下：</p>
<p dir="auto"><strong>26.85 → 39.81 tok/s</strong></p>
<p dir="auto">Decode 提升还是很明显的。</p>
<p dir="auto">不过超长 Context 下有一个需要特别注意的问题：</p>
<blockquote>
<p dir="auto"><strong>不能只看 Decode。</strong></p>
</blockquote>
<p dir="auto">512K 时：</p>
<h3>MTP OFF</h3>
<ul>
<li>TTFT：约 <strong>1009 s</strong></li>
<li>Decode：<strong>26.85 tok/s</strong></li>
</ul>
<h3>MTP ON</h3>
<ul>
<li>TTFT：约 <strong>1049 s</strong></li>
<li>Decode：<strong>39.81 tok/s</strong></li>
</ul>
<p dir="auto">MTP ON 的 TTFT 增加了大约 <strong>40 秒</strong>。</p>
<p dir="auto">而这轮测试的输出上限只有 512 tokens。</p>
<p dir="auto">所以在这种：</p>
<blockquote>
<p dir="auto"><strong>超长 Prompt + 短输出</strong></p>
</blockquote>
<p dir="auto">的场景里，虽然 MTP 明显提高了 Decode，但节省下来的生成时间还不足以覆盖前面增加的 TTFT 成本。</p>
<p dir="auto">本轮 512K 测试中：</p>
<blockquote>
<p dir="auto"><strong>MTP ON 的 E2E 反而慢约 34 秒。</strong></p>
</blockquote>
<p dir="auto">按照当前实测速度粗略计算，512K 这一档大概要输出：</p>
<p dir="auto"><strong>约 3,320 tokens</strong></p>
<p dir="auto">MTP 才可能开始进入 E2E 正收益区间。</p>
<p dir="auto">这里特别说明：</p>
<blockquote>
<p dir="auto"><strong>3,320 tokens 是根据当前实测速度推算出的 break-even，不是已经完成的实测点。</strong></p>
</blockquote>
<p dir="auto">所以我目前对两者的理解很简单：</p>
<blockquote>
<p dir="auto"><strong>KVMem 主要解决容量。</strong></p>
</blockquote>
<blockquote>
<p dir="auto"><strong>MTP 主要解决生成速度。</strong></p>
</blockquote>
<p dir="auto">两者可以叠加，但 MTP 到底值不值得开，需要结合 Prompt 长度和最终输出长度来看。</p>
<hr />
<h2>8. Retrieval：还有一点瑕疵，但整体已经可用</h2>
<p dir="auto">除了性能和显存，我也专门做了超长上下文 Recall 测试。</p>
<p dir="auto">测试方法比较简单：</p>
<ul>
<li>在超过 <strong>52 万 token</strong> 的长文本里，人工埋入 20 个彼此独立的 needle；</li>
<li>needle 大多是随机编号、数字或者孤立事实，本身几乎没有语义关联；</li>
<li>然后在超长上下文末尾逐个提问；</li>
<li>最后检查 20 个事实能不能准确找回来。</li>
</ul>
<p dir="auto">这其实是一个故意把 Retrieval 推向极端的 needle-in-a-haystack 测试：</p>
<blockquote>
<p dir="auto"><strong>信息只出现一次、距离非常远、语义线索很弱，然后要求在 50 多万 token 后精确找回。</strong></p>
</blockquote>
<p dir="auto">我此前用同类 Recall 方法测试的结果：</p>
<ul>
<li><strong>SGLang：100%</strong></li>
<li><strong>NInfer：100%</strong></li>
<li><strong>KVMem：18 / 20，90%</strong></li>
</ul>
<p dir="auto">所以 KVMem 目前还不能说完全无损，确实还有少量 retrieval miss。</p>
<p dir="auto">不过我不会把这个 <code>90%</code> 理解成：</p>
<blockquote>
<p dir="auto">“日常使用有 10% 概率出错。”</p>
</blockquote>
<p dir="auto">这种测试本身就是人为构造出来放大 Retrieval 边界的极端场景。</p>
<p dir="auto">正常 Agent、多轮对话、代码分析和长文档处理中，重要信息通常会有更多语义关联、上下文线索和重复引用，与这种“几十万 token 前只出现一次随机数字，然后最后精确追问”的情况并不完全相同。</p>
<p dir="auto">所以我的阶段性评价是：</p>
<blockquote>
<p dir="auto"><strong>和 SGLang、NInfer 的 100% Recall 相比，KVMem 目前还有一点瑕疵；但考虑到它已经能在 24GB RX 7900 XTX 上把 Context 推到 512K，我认为整体已经可用，瑕不掩瑜。</strong></p>
</blockquote>
<hr />
<h2>9. 长上下文真正带来的好处是什么？</h2>
<p dir="auto">把 Context 从 128K 推到 256K、512K，真正有价值的地方并不是“数字更大”。</p>
<p dir="auto">对实际 Agent 和长 Session 来说，更重要的是：</p>
<blockquote>
<p dir="auto"><strong>更多历史可以继续留在可访问范围内，而不用那么早就做 Context Compression、截断旧消息或者丢弃前面的工作状态。</strong></p>
</blockquote>
<p dir="auto">这一点和我之前测试 SGLang HiCache、NInfer Prefix Cache 时感受到的价值有一些相似，但三者的机制并不一样。</p>
<ul>
<li><strong>SGLang HiCache / NInfer Prefix Cache</strong> 更偏向：已经计算过的 KV 尽量复用，Cache 命中后可以减少重复 Prefill；</li>
<li><strong>KVMem</strong> 更偏向：让远大于 GPU active KV budget 的历史状态仍然可以被保存，并在需要时 retrieval / restore。</li>
</ul>
<p dir="auto">所以不能简单把 KVMem 等同于 SGLang HiCache 或 NInfer Prefix Cache。</p>
<p dir="auto">但对于长期运行的 Agent，它们最终都在改善同一个现实问题：</p>
<blockquote>
<p dir="auto"><strong>不要因为 Context 很快装满，就频繁压缩、截断或者丢掉已经积累的工作历史。</strong></p>
</blockquote>
<p dir="auto">比如一个 Agent 已经连续工作了几个小时，前面累计了：</p>
<ul>
<li>大量对话历史</li>
<li>工具调用结果</li>
<li>日志</li>
<li>文档内容</li>
<li>中间分析</li>
<li>已经做过的决策</li>
</ul>
<p dir="auto">传统 Context 不够时，就不得不开始：</p>
<ul>
<li>压缩历史</li>
<li>删除较早内容</li>
<li>重新总结</li>
<li>重新构造工作上下文</li>
</ul>
<p dir="auto">这些操作不仅增加管理成本，也可能造成信息损失。</p>
<p dir="auto">而更大的可用 Context，配合 KVMem 这类 KV 管理机制，可以让 Agent 更长时间保持连续工作状态。</p>
<p dir="auto">所以对我来说，512K 的意义并不只是：</p>
<blockquote>
<p dir="auto"><strong>“能塞进去 52 万 token。”</strong></p>
</blockquote>
<p dir="auto">更重要的是：</p>
<blockquote>
<p dir="auto"><strong>让一个长 Session 能保留更多已经发生过的事情，晚一点再被迫压缩和截断。</strong></p>
</blockquote>
<p dir="auto">这才是超长 Context 在实际使用里的价值。</p>
<hr />
<h2>10. 512K 和 Qwen3.8-27B 原生 256K Context 到底是什么关系？</h2>
<p dir="auto">这里需要单独解释一下，不然很容易把两个概念混在一起。</p>
<p dir="auto">Qwen3.8-27B 的原生 Context Length 是：</p>
<p dir="auto"><strong>262,144 tokens，也就是约 256K。</strong></p>
<p dir="auto">而本文测试的：</p>
<p dir="auto"><strong>512K / 523,744 tokens</strong></p>
<p dir="auto">首先证明的是另外一件事情：</p>
<blockquote>
<p dir="auto"><strong>KVMem 可以让 24GB RX 7900 XTX 在运行时承载并处理超过 52 万 token 的逻辑历史，而不会因为传统 Full-KV 的显存需求直接 OOM。</strong></p>
</blockquote>
<p dir="auto">也就是说，KVMem 主要解决的是：</p>
<blockquote>
<p dir="auto"><strong>KV Capacity</strong></p>
</blockquote>
<p dir="auto">它解决的是：</p>
<blockquote>
<p dir="auto"><strong>这么长的历史能不能装得下、能不能继续运行。</strong></p>
</blockquote>
<h3>512K 是总 Context，不是额外再加 512K</h3>
<p dir="auto">这里还有一个很容易误解的地方。</p>
<p dir="auto">本文说的：</p>
<p dir="auto"><strong>512K Context</strong></p>
<p dir="auto">指的是整个当前逻辑上下文的<strong>总长度约为 512K</strong>。</p>
<p dir="auto">不是：</p>
<p dir="auto"><strong>模型原生 256K + KVMem 再额外增加 512K</strong></p>
<p dir="auto">所以不存在：</p>
<p dir="auto"><strong>256K + 512K = 768K</strong></p>
<p dir="auto">这样的关系。</p>
<p dir="auto">更准确地理解：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>概念</th>
<th style="text-align:right">长度</th>
</tr>
</thead>
<tbody>
<tr>
<td>Qwen3.8-27B 原生 Context</td>
<td style="text-align:right">约 256K</td>
</tr>
<tr>
<td>本文 KVMem 测试的总逻辑 Context</td>
<td style="text-align:right">约 512K</td>
</tr>
<tr>
<td>512K 档实际 Prompt</td>
<td style="text-align:right">523,744 tokens</td>
</tr>
</tbody>
</table>
<p dir="auto">其中超过原生 256K 的部分，已经进入模型的长上下文扩展区域。</p>
<p dir="auto">所以：</p>
<blockquote>
<p dir="auto"><strong>512K 能跑，不等于模型原生 Context 变成了 512K。</strong></p>
</blockquote>
<p dir="auto">超过模型原生 256K 后，还可能涉及模型本身的长上下文扩展机制和外推质量，例如：</p>
<ul>
<li>RoPE Scaling</li>
<li>YaRN</li>
<li>超出原生训练长度后的 Recall / Reasoning Quality</li>
<li>长距离信息关联能力</li>
</ul>
<p dir="auto">因此需要把两个问题分开看：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>问题</th>
<th>KVMem 能解决吗？</th>
</tr>
</thead>
<tbody>
<tr>
<td>24GB 显存能不能承载 512K 逻辑历史</td>
<td><strong>可以，本文已实测</strong></td>
</tr>
<tr>
<td>Full-KV 会不会因为 512K 直接把 VRAM 撑爆</td>
<td><strong>KVMem 主要解决这个问题</strong></td>
</tr>
<tr>
<td>模型原生 Context 是否因此变成 512K</td>
<td><strong>不是</strong></td>
</tr>
<tr>
<td>模型在 512K 下质量是否和原生 256K 一样</td>
<td><strong>不能仅靠 KVMem 保证</strong></td>
</tr>
<tr>
<td>512K 下 Recall 是否可靠</td>
<td><strong>需要实际测试，本文已做初步验证</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">所以从工程角度看：</p>
<blockquote>
<p dir="auto"><strong>KVMem 负责解决“装不装得下、跑不跑得起来”。</strong></p>
</blockquote>
<p dir="auto">而模型本身的 Context Extension、RoPE Scaling 和长上下文能力负责回答：</p>
<blockquote>
<p dir="auto"><strong>“跑到这么长以后，还能不能答得准。”</strong></p>
</blockquote>
<p dir="auto">这也是为什么前面我没有因为“512K 跑通”就直接宣布“512K 完全无损”，而是另外做了 Recall 测试。</p>
<p dir="auto">所以本文里的 512K，最准确的理解应该是：</p>
<blockquote>
<p dir="auto"><strong>在 KVMem 帮助下，在我的机器上（64G系统内存），24GB RX 7900 XTX 已经具备承载约 512K 总逻辑 Context 的能力；但超过模型原生 256K 之后的最终质量，还要结合模型本身的长上下文扩展能力和实际 Recall 测试一起判断。</strong></p>
</blockquote>
<hr />
<h2>11. 一句话总结</h2>
<p dir="auto">这个 KVMem 是我最近做的一大堆乱七八糟测试中，唯一让我产生爽感的好东西。<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f436.png?v=fe25256ab4a" class="not-responsive emoji emoji-android emoji--dog" style="height:1.4em;width:auto;vertical-align:middle" title="🐶" alt="🐶" /></p>
<p dir="auto">跑到 <strong>512K</strong> 以后，依然还能保持：</p>
<ul>
<li>Prefill：<strong>520.34 tok/s</strong></li>
<li>Decode：<strong>26.85 tok/s</strong></li>
<li>VRAM：约 <strong>18～19.5 GiB</strong></li>
</ul>
<p dir="auto">逻辑 Context 从 128K 增长到 512K，扩大了 4 倍，而 Decode 基本没有变化。</p>
<p dir="auto">对于一张只有 24GB VRAM 的 RX 7900 XTX 来说，这已经把可用的 Context 空间向前推了很大一步。</p>
<blockquote>
<p dir="auto"><strong>24GB 显存，512K Context，能跑、能用，而且速度还没有塌，真牛 <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f402.png?v=fe25256ab4a" class="not-responsive emoji emoji-android emoji--ox" style="height:1.4em;width:auto;vertical-align:middle" title="🐂" alt="🐂" /> <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f44d.png?v=fe25256ab4a" class="not-responsive emoji emoji-android emoji--+1" style="height:1.4em;width:auto;vertical-align:middle" title=":+1:" alt="👍" /> 。</strong></p>
</blockquote>
<p dir="auto">这就是我这两天折腾 KVMem 以后最直观的感受。</p>
]]></description><link>https://lcz.me/topic/1961</link><generator>RSS for Node</generator><lastBuildDate>Mon, 12 Oct 2026 16:42:19 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/1961.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Sep 2026 05:40:33 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 7900 XTX 的可能性探索｜单卡篇（二）：KVMem 是个好东西—— 7900XTX 24GB 显存实测跑通 512K Context on Mon, 28 Sep 2026 02:49:42 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/naniandemeng" aria-label="Profile: naniandemeng">@<bdi>naniandemeng</bdi></a> 谢谢，这个增量长上下文目前有两个痛点，一个是cold prefill慢，第二个就是长上下文KV取回准确率不是100%。我准备给作者发个Ticket请他关注AMD这个版本的这个问题。</p>
]]></description><link>https://lcz.me/post/21231</link><guid isPermaLink="true">https://lcz.me/post/21231</guid><dc:creator><![CDATA[Ben Lee]]></dc:creator><pubDate>Mon, 28 Sep 2026 02:49:42 GMT</pubDate></item><item><title><![CDATA[Reply to 7900 XTX 的可能性探索｜单卡篇（二）：KVMem 是个好东西—— 7900XTX 24GB 显存实测跑通 512K Context on Mon, 28 Sep 2026 01:42:06 GMT]]></title><description><![CDATA[<p dir="auto">好贴，对7900来说很有价值的技术</p>
]]></description><link>https://lcz.me/post/21221</link><guid isPermaLink="true">https://lcz.me/post/21221</guid><dc:creator><![CDATA[naniandemeng]]></dc:creator><pubDate>Mon, 28 Sep 2026 01:42:06 GMT</pubDate></item></channel></rss>