LabHub

ブログ

LLMキャッシングの原理 — プロンプトキャッシングとPrefix Cacheはなぜお金を節約できるのか

한국어English日本語中文

はじめに — 「前半が同じなら安くなる」の謎

LLM APIのプロンプトキャッシングを初めて見ると不思議です。同じ質問を二度すると安くなるのではなく、プロンプトの前半が同じなら安くなります。後半が完全に違っても構いません。しかも、あるプロバイダーはキャッシュに「書く」費用を割増しで取り、「読む」費用は10分の1に割り引きます。この奇妙な価格表はマーケティングではなく、トランスフォーマー内部の物理学をそのまま反映したものです。

この記事はその物理学を底から登っていきます。トランスフォーマーがテキストを生成するとき内部で何が起きているのか、KVキャッシュとは何でなぜプレフィックス(前半)にだけ効くのか、vLLMやSGLangといったサービングエンジンがそれをどう実装しているのか、そしてAnthropic・OpenAIのプロンプトキャッシングを実践でどう設計すべきかまで。

ステップ1 — 推論は二つの局面に分かれる:PrefillとDecode

トランスフォーマー推論には、性格の全く異なる二つの局面があります。

プロンプトキャッシングが節約してくれるのは、まさにprefill局面の演算です。10万トークンのシステムプロンプトがキャッシュにあれば、その10万トークンを再びprefillする必要はありません。だからキャッシュヒットはコストだけでなくTTFTを劇的に縮めます。

ステップ2 — アテンションとK/V:トークンごとに作られる名刺

なぜprefillを飛ばせるのでしょうか。アテンションの内部を見る必要があります。

トランスフォーマーの各層で、各トークンは三つのベクトルに変換されます — Query(質問)、Key(キー)、Value(値)。直観的に言えば、各トークンは自分を紹介する名刺(K)と中身(V)を作っておき、新しいトークンは自分の質問(Q)で以前のトークンたちの名刺を眺めて関連度を計算し、関連度に応じて中身を混ぜていきます。

核心的な性質が一つあります。GPT系モデルのアテンションは因果的(causal)です — 各トークンは自分より前のトークンしか見られません。これが意味すること:

トークンiのKとVは、トークン1からiまでだけの関数だ。後ろに何が来ようと絶対に変わらない。

この性質があらゆるキャッシングの根です。「ここまでのテキスト」が同じなら、各トークンのK/Vベクトルはビット単位で同一に計算されます。なら、一度計算したものをなぜまた計算するのか? 保存しておけばいい。

ステップ3 — KVキャッシュ:保存しておけばいい

KVキャッシュがまさにその保管庫です。decode局面で新しいトークンを生成するとき、モデルは以前の全トークンのK/Vを必要とします。キャッシュがなければトークン生成のたびにこれまでの全シーケンスを再計算する羽目になり、生成コストは長さの二乗で爆発します。KVキャッシュがあれば、新トークンのQ/K/Vだけ計算し、以前のものはキャッシュから読みます。

タダではありません。KVキャッシュはメモリを食います。トークン一つが占めるサイズはおよそ:

トークンあたりKVキャッシュ = 2(KとV)× 層数 × KVヘッド数 × ヘッド次元 × バイト数

例:7Bクラスのモデル(32層、隠れ次元4096、fp16)
   = 2 × 32 × 4096 × 2バイト ≈ トークンあたり約512KB
   → 4,000トークンの会話一つ ≈ 約2GB
   → 同時ユーザー数十人でGPUメモリはあっという間に枯渇

このメモリ圧力が最新アーキテクチャの多くを説明します — GQA(複数のQヘッドがK/Vヘッドを共有)やMQAはKVヘッド数を減らしてキャッシュを数分の一にする設計であり、KVキャッシュ量子化(FP8/INT4)も同じ圧力から生まれました。長文コンテキスト時代の本当のコストは、重みではなくKVキャッシュであることが多いのです。

ステップ4 — Prefix Cache:リクエスト間でも再利用する

ここまでのKVキャッシュは一つのリクエスト内の話でした。Prefix Cache(プレフィックスキャッシュ)はこれをリクエスト間に拡張します。

二つのリクエストが同じ前半部分(例:同じシステムプロンプト+同じ文書)を共有するなら、その部分のK/Vは完全に同一です — 先ほどの因果性のおかげで。だから最初のリクエストで計算したK/Vブロックを捨てずに保管し、次のリクエストでプレフィックスが一致すればprefillなしにそのまま続きから使えばいい。

なぜ「前半」だけなのか? 因果性の裏面です。トークンiのK/Vは1..iの関数なので、途中の一トークンでも変われば、その地点以降のすべてのトークンのK/Vが変わります。プロンプトの途中にタイムスタンプを一つ挟むと、その後ろの10万トークンのキャッシュが全部無効になる理由です。キャッシュは「同じ内容を含む」ではなく「バイト単位で同一のプレフィックス」にだけ反応します。

実際のサービングエンジンの実装:

ステップ5 — プロバイダーのプロンプトキャッシング:価格表の読み方

APIプロバイダーの「プロンプトキャッシング」は、このprefix cacheを商品化したものです。これで価格表が物理学として読めます。

Anthropic(Claude) — 明示的キャッシング。リクエストにcache_controlブレークポイント(最大4個)を付けます。

OpenAI — 自動キャッシング。1024トークン以上のプロンプトでプレフィックスが一致すれば表示なしで適用され、キャッシュされた入力トークンは公開基準で50%割引です。明示マーカーがなく楽ですが、どこまでキャッシュされたかの制御権もありません。

どちらの方式でも検証方法は同じです — レスポンスのusageフィールドを見てください。Anthropicならcache_read_input_tokensがゼロでないことが、キャッシュが実際に読まれている証拠です。繰り返しリクエストでずっとゼロなら、どこかに沈黙のキャッシュ破壊者がいます。

ステップ6 — 実践設計ルール

原理が分かればルールは自然に出てきます。

おわりに — 価格表は物理学だ

まとめるとこう圧縮されます。アテンションは因果的なので前方トークンのK/Vは不変であり、KVキャッシュはそれを一つのリクエスト内で、prefix cacheはリクエスト間で再利用し、プロンプトキャッシングの価格表(書き込み割増、読み取り割引、プレフィックス限定、最小長)はその再利用のコスト構造をそのまま価格に写したものです。「なぜ前半だけ?」という問いの答えはマーケティング政策ではなく、トークンiのK/Vは1..iだけの関数という一行の数学でした。

サービングコスト全般の絵は AIモデル開発ライフサイクル のサービング節と、GPUを分割して使う MIGガイド に続きます。

参考資料

コメント

まだコメントはありません。

ログインするとコメントできます