<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>KV Cache on KnightLi的博客</title>
        <link>https://www.knightli.com/zh-tw/tags/kv-cache/</link>
        <description>Recent content in KV Cache on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-tw</language>
        <lastBuildDate>Thu, 23 Apr 2026 12:13:04 +0800</lastBuildDate><atom:link href="https://www.knightli.com/zh-tw/tags/kv-cache/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>8G 顯存跑 llama.cpp 怎麼調：32K 更穩，64K 要開 KV Cache 量化</title>
        <link>https://www.knightli.com/zh-tw/2026/04/23/llama-cpp-8g-vram-32k-64k-kv-cache-tuning/</link>
        <pubDate>Thu, 23 Apr 2026 12:13:04 +0800</pubDate>
        
        <guid>https://www.knightli.com/zh-tw/2026/04/23/llama-cpp-8g-vram-32k-64k-kv-cache-tuning/</guid>
        <description>&lt;p&gt;&lt;code&gt;8G&lt;/code&gt; 顯存到底還能不能把本地大模型跑順，尤其是在長上下文場景下還能不能保住速度，這是很多人在折騰 &lt;code&gt;llama.cpp&lt;/code&gt; 時都會遇到的問題。&lt;/p&gt;
&lt;p&gt;核心結論可以先記住三條：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;對 &lt;code&gt;8G&lt;/code&gt; 顯存來說，&lt;code&gt;32K&lt;/code&gt; 上下文通常是更穩的平衡點&lt;/li&gt;
&lt;li&gt;如果一定要跑 &lt;code&gt;64K&lt;/code&gt;，&lt;code&gt;KV Cache&lt;/code&gt; 量化基本是必選項&lt;/li&gt;
&lt;li&gt;在全顯卡運行場景裡，盲目拉高 &lt;code&gt;CPU&lt;/code&gt; 執行緒數，反而可能讓速度明顯下降&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;一先解釋清楚32k64k-和-kv-cache-是什麼&#34;&gt;一、先解釋清楚：32K、64K 和 KV Cache 是什麼
&lt;/h2&gt;&lt;p&gt;很多人第一次看這類調優文章，最容易卡住的就是這三個詞。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;32K&lt;/code&gt; 和 &lt;code&gt;64K&lt;/code&gt; 說的是上下文長度，也就是模型一次最多能處理多少 &lt;code&gt;token&lt;/code&gt;。這裡的 &lt;code&gt;K&lt;/code&gt; 就是千，&lt;code&gt;32K&lt;/code&gt; 大約是 &lt;code&gt;32000 token&lt;/code&gt;，&lt;code&gt;64K&lt;/code&gt; 大約是 &lt;code&gt;64000 token&lt;/code&gt;。上下文越長，模型一次能看到的歷史內容越多，適合長文件問答、長對話和多輪分析。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;KV Cache&lt;/code&gt; 則是模型為了加速連續生成而保留的一份中間結果快取。你可以把它理解成：模型已經讀過、算過的一部分內容，不會每次都從頭重算，而是把關鍵結果先存起來，後面繼續接著用。這裡的 &lt;code&gt;K&lt;/code&gt; 和 &lt;code&gt;V&lt;/code&gt;，來自 Transformer 裡的 &lt;code&gt;Key&lt;/code&gt; 和 &lt;code&gt;Value&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;為什麼這三個詞總是一起出現？因為：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;32K&lt;/code&gt;、&lt;code&gt;64K&lt;/code&gt; 決定你想讓模型一次記住多長內容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;KV Cache&lt;/code&gt; 決定為了維持這段記憶，要額外占多少顯存&lt;/li&gt;
&lt;li&gt;上下文越長，&lt;code&gt;KV Cache&lt;/code&gt; 通常越大，顯存壓力也越高&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以很多長上下文變慢的問題，本質上並不是模型「不會算」，而是快取太大，把顯存擠到了臨界點。&lt;/p&gt;
&lt;h2 id=&#34;二為什麼-32k-和-64k-的速度會差這麼多&#34;&gt;二、為什麼 32K 和 64K 的速度會差這麼多
&lt;/h2&gt;&lt;p&gt;這裡用《三體》大約 &lt;code&gt;3&lt;/code&gt; 萬字的文本做壓力測試，對比 &lt;code&gt;32K&lt;/code&gt; 和 &lt;code&gt;64K&lt;/code&gt; 兩種上下文設定。結果很誇張：在文件長度接近的情況下，&lt;code&gt;64K&lt;/code&gt; 模式的速度顯著下降，總耗時也明顯拉長。&lt;/p&gt;
&lt;p&gt;問題不在模型突然變笨，而在顯存邊界被撞到了。&lt;/p&gt;
&lt;p&gt;當 &lt;code&gt;32K&lt;/code&gt; 模式下，模型權重加快取還能基本塞進 &lt;code&gt;8G&lt;/code&gt; 顯存裡，資料大多走顯卡顯存帶寬，速度還能維持在比較可用的區間。但一旦切到 &lt;code&gt;64K&lt;/code&gt;，快取體積繼續上漲，總占用逼近甚至超過顯存上限，系統就會把部分資料擠到記憶體裡。&lt;/p&gt;
&lt;p&gt;這時候真正掉下去的，不是算力，而是帶寬。&lt;/p&gt;
&lt;p&gt;也就是說，很多人看到的是「上下文翻倍後速度暴跌」，本質上其實是資料路徑從顯存掉到了共享記憶體或系統記憶體，推理鏈路不再跑在高速通道上。&lt;/p&gt;
&lt;h2 id=&#34;三64k-還能不能跑關鍵在-kv-cache-量化&#34;&gt;三、64K 還能不能跑，關鍵在 KV Cache 量化
&lt;/h2&gt;&lt;p&gt;第二個很關鍵的結論，是 &lt;code&gt;KV Cache&lt;/code&gt; 量化對 &lt;code&gt;8G&lt;/code&gt; 顯存使用者特別重要。&lt;/p&gt;
&lt;p&gt;如果不改變模型本身，只針對快取做量化，長上下文下最直接的收益就是把快取占用壓縮下來，讓原本已經溢出的那部分重新回到顯存裡。這樣一來，&lt;code&gt;64K&lt;/code&gt; 模式雖然依然比 &lt;code&gt;32K&lt;/code&gt; 更吃資源，但至少不會直接跌進最慢的區間。&lt;/p&gt;
&lt;p&gt;換句話說：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;32K&lt;/code&gt; 更像是 &lt;code&gt;8G&lt;/code&gt; 顯存的預設推薦區間&lt;/li&gt;
&lt;li&gt;&lt;code&gt;64K&lt;/code&gt; 不是完全不能跑&lt;/li&gt;
&lt;li&gt;但如果不上快取量化，效能很容易從「能用」直接掉到「很難用」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你的目標是盡量穩定地跑長上下文，那優先順序通常應該是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先確認顯存是否已經逼近上限&lt;/li&gt;
&lt;li&gt;再決定是否開啟 &lt;code&gt;KV Cache&lt;/code&gt; 量化&lt;/li&gt;
&lt;li&gt;最後才去繼續嘗試更激進的吞吐量參數&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;四gpu-占用不高不代表顯卡沒幹活&#34;&gt;四、GPU 占用不高，不代表顯卡沒幹活
&lt;/h2&gt;&lt;p&gt;這是一個很容易打破直覺的點。&lt;/p&gt;
&lt;p&gt;很多人看到工作管理員裡 &lt;code&gt;GPU&lt;/code&gt; 使用率只有二三十，就會懷疑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是不是參數沒設對&lt;/li&gt;
&lt;li&gt;是不是模型沒真正跑到顯卡上&lt;/li&gt;
&lt;li&gt;是不是顯卡根本沒吃滿&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但這組測試給出的判斷是，&lt;code&gt;llama.cpp&lt;/code&gt; 這類推理很多時候首先卡的不是核心算力，而是顯存讀寫速度。&lt;/p&gt;
&lt;p&gt;也就是說，顯卡核心可能很快就把一批計算做完了，但後面還得等下一批權重和快取資料搬過來。於是你看到的現象就會變成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;核心占用不算高&lt;/li&gt;
&lt;li&gt;但整體速度還是上不去&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這不是顯卡在偷懶，而是資料通路太窄。&lt;/p&gt;
&lt;p&gt;所以看本地大模型速度時，不能只盯著 &lt;code&gt;GPU Usage&lt;/code&gt;。顯存容量、顯存帶寬、快取是否溢出，往往更影響最終體驗。&lt;/p&gt;
&lt;h2 id=&#34;五調大吞吐量參數確實可能再快一截&#34;&gt;五、調大吞吐量參數，確實可能再快一截
&lt;/h2&gt;&lt;p&gt;這裡還做了一個思路很清晰的測試：既然顯卡核心並沒有完全忙滿，那能不能透過調大吞吐量相關參數，讓顯卡一次處理更多資料，把並行能力進一步壓出來。&lt;/p&gt;
&lt;p&gt;測試結果表明，這種做法確實有機會把速度再往上拉一段。&lt;/p&gt;
&lt;p&gt;但這裡也有一個前提：顯存還得扛得住。&lt;/p&gt;
&lt;p&gt;因為吞吐量相關參數調大之後，往往會帶來額外顯存占用。如果你本來就在 &lt;code&gt;64K&lt;/code&gt;、高快取、顯存見底的狀態下繼續往上推，就很容易出現兩種情況：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接崩潰&lt;/li&gt;
&lt;li&gt;沒崩，但被迫進入更慢的共享記憶體模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以更穩妥的順序通常不是「先把參數拉滿」，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先守住顯存邊界&lt;/li&gt;
&lt;li&gt;再考慮吞吐量優化&lt;/li&gt;
&lt;li&gt;每調一步都重新看速度和穩定性&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;六cpu-執行緒不是越多越好&#34;&gt;六、CPU 執行緒不是越多越好
&lt;/h2&gt;&lt;p&gt;這也是整篇內容裡最值得記住的坑點之一。&lt;/p&gt;
&lt;p&gt;很多人做本地推理調優時，容易下意識覺得執行緒越多越快，既然機器有那麼多執行緒，不用滿就像浪費。但實測給出的結果恰恰相反：在模型已經主要跑在顯卡上的情況下，強行把 &lt;code&gt;CPU&lt;/code&gt; 執行緒拉高，效能反而會明顯變差。&lt;/p&gt;
&lt;p&gt;原因不複雜。&lt;/p&gt;
&lt;p&gt;在全顯卡運行時，&lt;code&gt;CPU&lt;/code&gt; 更像是調度者和預處理協作者，而不是主力計算單元。這時候如果開太多執行緒，CPU 端的執行緒競爭、調度切換和上下文切換開銷都會變重，最終把本來應該更流暢的資料流打亂。&lt;/p&gt;
&lt;p&gt;結果就是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CPU&lt;/code&gt; 更忙了&lt;/li&gt;
&lt;li&gt;但整體速度變慢了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以在這種場景下，預設設定或者較低執行緒數，往往比一味拉滿更靠譜。&lt;/p&gt;
&lt;h2 id=&#34;七對-8g-顯存使用者更實用的一套思路&#34;&gt;七、對 8G 顯存使用者更實用的一套思路
&lt;/h2&gt;&lt;p&gt;如果把上面的結論壓成一套更容易執行的思路，大概可以整理成這樣：&lt;/p&gt;
&lt;h3 id=&#34;1-先把-32k-當成預設目標&#34;&gt;1. 先把 32K 當成預設目標
&lt;/h3&gt;&lt;p&gt;如果你用的是 &lt;code&gt;8G&lt;/code&gt; 顯存顯卡，先別急著追 &lt;code&gt;64K&lt;/code&gt;。&lt;code&gt;32K&lt;/code&gt; 往往是速度、穩定性和顯存占用之間更現實的平衡點。&lt;/p&gt;
&lt;h3 id=&#34;2-想上-64k先處理快取問題&#34;&gt;2. 想上 64K，先處理快取問題
&lt;/h3&gt;&lt;p&gt;不要先想「還能不能再榨一點速度」，而是先確認 &lt;code&gt;KV Cache&lt;/code&gt; 有沒有量化、顯存是不是已經壓線。&lt;/p&gt;
&lt;h3 id=&#34;3-不要用-gpu-占用率判斷一切&#34;&gt;3. 不要用 GPU 占用率判斷一切
&lt;/h3&gt;&lt;p&gt;低占用不一定代表設定錯了，也可能只是顯存帶寬在拖後腿。&lt;/p&gt;
&lt;h3 id=&#34;4-吞吐量優化可以做但別越過顯存邊界&#34;&gt;4. 吞吐量優化可以做，但別越過顯存邊界
&lt;/h3&gt;&lt;p&gt;這類參數確實能帶來收益，但前提是顯存還有餘量。&lt;/p&gt;
&lt;h3 id=&#34;5-cpu-執行緒先保守再逐步測試&#34;&gt;5. CPU 執行緒先保守，再逐步測試
&lt;/h3&gt;&lt;p&gt;如果模型已經基本跑在顯卡上，CPU 執行緒並不是越高越好。先用預設值或低執行緒值測試，再看是否值得繼續調整。&lt;/p&gt;
&lt;h2 id=&#34;結語&#34;&gt;結語
&lt;/h2&gt;&lt;p&gt;這組內容最有價值的地方，不只是給出幾個測試數字，而是把一個經常被忽略的事實講清楚了：&lt;/p&gt;
&lt;p&gt;本地大模型調優，很多時候拼的不是「有沒有把所有參數開到最大」，而是你有沒有搞清楚瓶頸到底在算力、顯存容量、顯存帶寬，還是在 &lt;code&gt;CPU&lt;/code&gt; 調度。&lt;/p&gt;
&lt;p&gt;對 &lt;code&gt;8G&lt;/code&gt; 顯存使用者來說，真正更穩的思路通常不是硬衝最長上下文，而是先守住顯存邊界，再決定要不要繼續往上加。&lt;/p&gt;
&lt;p&gt;如果只記一句話，那就是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;32K&lt;/code&gt; 往往是 &lt;code&gt;8G&lt;/code&gt; 顯存更穩的工作區間；&lt;code&gt;64K&lt;/code&gt; 不是不能跑，但前提是你已經把 &lt;code&gt;KV Cache&lt;/code&gt; 和顯存占用管住了。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
