プロンプトキャッシュの解読:PagedAttention原理から10倍のコスト削減と効率向上まで @dejavucoderによるこの記事では、特に@vllm_projectのPagedAttentionテクノロジーをベースに、Prompt Cachingの根底にある原理を深く掘り下げています。著者は開発中に陥った落とし穴の経験に基づき、開発者がキャッシュメカニズムに関して抱く多くの誤解を正し、非常に実用的な最適化の提案を提供しています。 根本的な誤解と真実:キャッシュはグローバルであり、プライベートではない。誤解:筆者(の多くと同様)は当初、プロンプトキャッシュは「ユーザーセッション」に基づいていると考えていました。つまり、同じダイアログボックス内で同じユーザーが送信する後続のメッセージのみが、以前にキャッシュされたメッセージを利用できるというわけです。 真実は、プロンプト キャッシュはユーザー ベースではなくコンテンツ ベースであるということです。 • コアロジック: システムプロンプトまたはツール定義が完全に一貫したテキストである限り、ユーザー A によって生成されたキャッシュはユーザー B によって完全に再利用できます。 • 重要性: これは、同時実行性の高いシナリオでは、プレフィックスが一貫している限り、システムは「グローバル再利用」を実現でき、冗長な計算が大幅に削減されることを意味します。 キャッシュはなぜ必要なのか?(コストと速度) LLM の推論プロセスは 2 つの段階に分かれており、この違いを理解することがキャッシュの価値を理解する鍵となります。 • 事前入力段階:この段階では、入力された多数のプロンプトを処理し、それらのキーと値のキャッシュを計算します。このプロセスは計算負荷が高く、多くの計算能力を消費します。 • デコードフェーズ:レスポンストークンを1つずつ生成します。このプロセスはメモリと帯域幅を大量に消費します。 • キャッシュなし: リクエストが届くたびに、プロンプトの最初の 90% が同じであっても、事前入力のためにモデルを再計算する必要があり、時間がかかり、コストも高くなります。 • キャッシュをヒット: 面倒な事前入力計算を直接スキップできるため、トークンの入力コストが 10 倍削減され、最初の文字生成の速度が大幅に向上します。 技術発表:PagedAttention 従来のキー値キャッシュ管理は非常に非効率で、連続したビデオメモリの大きなブロックを事前に割り当てる必要があり、簡単に断片化と無駄が生じます。vLLM は、オペレーティング システムのメモリ管理、つまりページングの概念を導入します。 • ブロック: システムは、連続した大きなメモリブロックを割り当てる代わりに、KVキャッシュを固定サイズの「ブロック」に分割します。これらのブロックは、物理ビデオメモリ内に散在し、連続していない場合があります。 • ブロックハッシュ – 効果的なキャッシュの鍵: システムはどのようにして「この文章は以前に計算されたことがある」と知るのでしょうか?それはブロックのハッシュ値を計算します。 • 親ブロックの依存性: ブロックのハッシュ値は、そのブロック自体の内容だけでなく、前のブロックのハッシュ値にも依存します。 • 連鎖反応:これはブロックチェーンに似ています。現在のハッシュ値は、「最初から」すべてが完全に一致している場合にのみ一致します。これにより因果関係の正確性が保証されます。中間セグメントを再利用することはできず、プレフィックスが完全に一致する必要があります。 • グローバル検索: 新しいリクエストが到着すると、システムはそのプロンプトワードのブロックハッシュを計算し、グローバルハッシュテーブルでそれを参照します。一致するものが見つかった場合、それ以上の計算を行うことなく、既存のメモリブロックを直接参照します。 開発者向けの実践的なアドバイス: システムを「だまして」キャッシュをヒットさせるにはどうすればよいでしょうか? キャッシュヒット率を最大化するには、システムが異なるリクエストを「同じ」ものとして扱うようにする必要があります。この記事では、いくつかの黄金律を紹介します。 • 安定したプレフィックスを維持します。 すべての静的コンテンツ (システム プロンプト、ツール定義、サンプル テキスト) を先頭に配置します。 • 反例: プロンプトの先頭に「現在の時刻」または「ユーザー名」を入力すると、ハッシュ チェーン全体が最初から壊れてしまい、後続のコンテンツは、たとえ同一であってもキャッシュ内で再利用できません。 • 決定論的なシリアル化 JSON 形式を使用してデータを送信する場合 (ユーティリティ呼び出しなど)、キーの順序を一定に保つ必要があります。 ヒント: Pythonでは`json.dumps(..., sort_keys=True)`を使用してください。`{ "a": 1, "b": 2 }`と`{ "b": 2, "a": 1 }`は意味的には同じですが、異なる文字列を生成するため、キャッシュミスが発生します。 • 追加専用モード 複数ターンのダイアログ履歴を管理する際は、新しいコンテンツは最後にのみ追加するようにしてください。履歴の途中で変更したり切り捨てたりしないでください。途中で変更すると、後続のキャッシュチェーン全体が無効になります。 • ツール定義の変更には注意してください。ツール定義は、モデルによってシステムプロンプトに追加されることがよくあります。ユーザーごとに異なるツールを動的に有効/無効にすると、プレフィックスが変更され、キャッシュが無効化される可能性があります。 要約 プロンプトキャッシングの本質は「メモリ」ではなく「計算結果の再利用」にあります。基盤となるブロックとハッシュチェーンのメカニズムを理解することで、開発者は「プレフィックス」がなぜそれほど重要なのかを理解できるようになります。 つまり、常に変更されないもの (システム コマンド、背景ドキュメント、ツール リスト) を先頭に置き、変更されるもの (ユーザーの質問、動的変数) を最後に置くということです。 原文を読む
スレッドを読み込み中
X から元のツイートを取得し、読みやすいビューを準備しています。
通常は数秒で完了しますので、お待ちください。
