KVキャッシュの量子化:VRAMを節約(長 contexte)
VRAMにはモデルを読み込むだけの容量がありますが、コンテキストを16kまたは32kトークンに拡大すると、容量が不足します。その原因はKVキャッシュです。KVキャッシュはコンテキストの長さに比例して増加する隠れたメモリであり、長いプロンプトではモデル本体と同程度の容量を消費することがあります。KVキャッシュの量子化により、Q8またはQ4に圧縮することで、同じGPUカード上で保持可能なコンテキストを2倍にできます。以下は、Ollamaおよびllama.cppでこれを有効にする方法、具体的な性能向上の数値、そして品質への実際の影響です。
#KVキャッシュがVRAMを消費する理由は?
LLMがテキストを生成する際、新しいトークンごとにプロンプト全体について注意を再計算するわけではありません。すでに確認した各トークンのキー(K)ベクトルとバリュー(V)ベクトルをメモリに保持します。これがKVキャッシュであり、これが生成を高速化します。問題は、このメモリがコンテキストの長さに比例して線形に増加することです。コンテキストを倍にすると、KVキャッシュも倍になります。
数百トークン程度の短いプロンプトでは、無視できるほどです。しかし、大きな文書を使うRAG、文字起こしの要約、長期記憶を持つエージェントなどを扱い始めると、コンテキストが急増し、KVキャッシュもそれに伴って膨らみます。70Bモデルで32kのコンテキストを使う場合、モデル自体の約40GBに加えて、KVキャッシュだけで10GBを超えることがあります。長いプロンプトでメモリ不足(out of memory)を引き起こすのは、多くの場合、モデルそのものではなくKVキャッシュです。
#KVキャッシュはどれくらいのメモリを使うのか
お使いのマシンで、プライベートかつ無料のChatGPTを1時間で構築 — LM Studio、Ollama、Open WebUI、ご自身のドキュメント、クラウド不要。
- 永久に利用できるオンラインスペース
- PDF + ファイル
- 生涯アップデート
KV キャッシュのサイズは、モデルのレイヤー数、アテンションの次元、コンテキスト長、保存時の精度という四つの要因で決まります。FP16(デフォルト)での概算式は、2(K と V)× レイヤー数 × dim_kv × コンテキスト長 × 2 バイトです。実用上の目安として、32k トークンのコンテキストで FP16 を使う場合の、おおよその容量を以下に示します。
- 7-9B(例:Qwen 3.5 9B、Granite 4.2 8B)
- 32kのKVキャッシュは約2〜4GB(アーキテクチャにより異なります。GQAは大きな助けになります)。
- 14B
- コンテキストが32kトークンの場合、約4~6GB。
- 32B
- 32kトークンで約8〜10GB。
- 70B
- 32kトークンで約10〜16GBを使用し、これが制約になることがよくあります。
#KVキャッシュの量子化がもたらす変化
モデルの重みと同様に、キャッシュの各値を16ビット(FP16)ではなく、8ビット(Q8_0)または4ビット(Q4_0)で保存します。これにより、キャッシュのメモリは機械的に2分の1(Q8)または4分の1(Q4)に削減されます。KVキャッシュは長いコンテキストにおいてVRAMの大きな割合を占める可能性があるため、その効果は直接的です。VRAMが一定の場合、Q8では保持可能なコンテキスト長を約2倍にできます。
- FP16
- 基準となる精度で、精度の低下はありませんが、メモリ消費量は最も多くなります。デフォルトの形式です。
- Q8_0
- 半分のメモリで、ほとんどのモデルにおいて品質の低下はほぼ検出できません。最も適切なバランスです。
- Q4_0
- メモリは四分の一に抑えられますが、測定可能な品質の低下が発生します。低下の程度はモデルによって異なります。VRAMが明確なボトルネックとなる場合にのみ使用してください。
#Ollama でのKVの量子化を有効にする
Ollamaでは、デーモンの2つの環境変数でKVキャッシュの量子化を設定できます。まずFlash Attentionを有効にしてから、キャッシュの種類を選ぶ必要があります。これらの変数はOllamaサービスに設定するもので、ollama runの実行時に設定するものではありません。
- 01Flash Attentionを有効にするdaemonの環境変数にOLLAMA_FLASH_ATTENTION=1を設定してください。これはFP16以外のキャッシュに必要な前提条件です。
- 02キャッシュのタイプを選択OLLAMA_KV_CACHE_TYPE に希望する値を設定してください:f16(デフォルト)、q8_0(推奨)、または q4_0(量子化を強くかける設定)。
- 03デーモンを再起動環境変数はサービスの起動時にのみ読み込まれます。Ollama を再起動してください。環境変数が有効になります。
- 04改善効果を確認するモデルを大きなコンテキストで読み込み、nvidia-smi または ollama ps でVRAMを監視してください。num_ctxを以前より高い値に設定できるはずです。
#llama.cppで有効化
llama.cppでのコマンド実行では、K(キー)とV(値)のキャッシュの量子化はそれぞれ異なるフラグで制御され、さらにFlash Attentionフラグも使用できます。KとVを独立して量子化できますが、実際には同じレベルに設定することが一般的です。
- -fa
- Flash Attention を有効にします。このフラグがないと、-ctk/-ctv に f16 より低い精度を指定した場合に失敗します。
- -ctk q8_0
- キーのキャッシュを8ビットで量子化します。指定できる値:f16、q8_0、q4_0、q4_1、q5_0、q5_1。
- -ctv q8_0
- 値のキャッシュを量子化します。指定できる値は-ctkと同じです。
- -c 32768
- 目標とするコンテキスト長です。量子化により、メモリ容量を超えずにこの値を引き上げられます。
#コンテキスト長はどれだけ伸ばせるか:実際の数値
実際の効果は、使えるVRAM容量のうちKVキャッシュが占める割合によって変わります。モデルが余裕を持って収まる場合、キャッシュを量子化しても、少し余裕が増える程度です。モデルがすでにVRAMを使い切っている場合は、使えるコンテキスト長が8kになるか24kになるかを左右することがあります。以下は、VRAM容量を変えずに観測された、おおよその値です:
- FP16 → Q8_0
- キャッシュ容量が半分になります。実際には、キャッシュがメモリ使用量の大部分を占めていた場合、扱えるコンテキストの長さは約 2 倍になります。
- FP16 → Q4_0
- キャッシュ容量は4分の1に。扱えるコンテキスト長は最大で約3〜4倍になりますが、測定可能な品質低下を伴います。
- RTX 4080 16GB で動かす 14B モデルの例
- FP16では約16kのコンテキスト長が、Q8_0では約32k以上に拡大します。モデルとその他の必要なメモリを合わせても、同じ16 GBに収まります。
- RTX 4090 24GBで32Bモデルを使う例
- キャッシュをQ8_0に切り替えると、CPUへのオフロードなしで、RAGの長い文書を処理できるようになることがよくあります。
#モデルごとの品質への影響
そこが核心となる問いです。キャッシュを量子化するとアテンションにノイズが入り、モデルによって反応は異なります。コミュニティによるテストから見えてきた経験則は、次のとおりです。
- キャッシュにおけるQ8_0
- 大多数のモデルでは、違いはほとんど見分けられません。パープレキシティと体感的な品質は、FP16とほぼ同じです。ほとんど迷わず、標準で有効にしてよい設定です。
- キャッシュにおけるQ4_0
- 品質の低下は目に見えますが、その程度はさまざまです。ほとんど影響を受けないモデルもあれば、非常に長いコンテキストで話が脱線したり、話の筋を見失ったり、ハルシネーションが増えたりするモデルもあります。ご自身の用途でテストすること。
- GQAを採用したモデル
- キャッシュがすでにコンパクトで整った構造になっているため、一般にキャッシュの量子化に対してより頑健です。
- 精度が重要なタスク(コード、計算、厳密な抽出)
- Q4による品質低下の影響を受けやすくなります。事実の正確さが求められる用途では、すべてQ8を維持してください。
#トラブルシューティング
- 「flash attention required」と表示される、またはキャッシュが無視される
- -fa(llama.cpp)またはOLLAMA_FLASH_ATTENTION=1(Ollama)の設定を忘れています。量子化キャッシュは通知なしでFP16に戻されるか、エラーが発生します。
- VRAMの使用量の削減が確認できません
- コンテキストが短すぎるため、キャッシュのメモリ使用量が大きくありません。効果が現れるのは長いプロンプトの場合だけです。num_ctx / -cを増やして確認してください。
- 長いプロンプトで品質が低下する
- おそらく、Q4でモデルがうまく処理できない状況です。Kをq8_0(またはすべてq8_0)に変更して再テストしてください。
- Ollamaの変数が反映されない
- これらはデーモンの起動時にのみ読み込まれます。設定を保存した後、サービスを再起動し、プロセス ollama がこれらの設定を正しく認識しているかを確認してください。
- 量子化しても依然としてOOMが発生する
- メモリ容量を超えているのは、キャッシュではなくモデル自体です。重みも量子化する(Q4_K_M)か、モデルを一段小さいサイズに変更してください。
#さらに詳しく
KVキャッシュの量子化は、ローカルで大きなコンテキストを扱うための手法の一つです。以下のガイドで、関連する情報を補えます。
- ローカルLLMのFlash Attention 2:有効化して効果をベンチマークで測定する
- KVキャッシュ量子化の前提条件であり、それ自体でもメモリ消費の削減と速度向上をもたらします。お使いの環境でFlash Attentionがまだ有効になっていない場合は、まずこちらを読んでください。
- 量子化の選択(Q4、Q5、Q8、FP16)
- モデルの重みを量子化するためのものです。重みはVRAMを大きく消費するもう一つの要素で、その量子化はキャッシュの量子化と相互に補完し合います。
- Ollama のインストール:Windows、macOS、Linux
- まだ実行環境が整っていない場合に。適切な構成を選べるよう、GPU の要件も説明しています。
ご意見、誤りのご指摘、補足はありますか?ぜひお知らせください。皆さんにとってより良いガイドにするために役立ちます。