vLLM x Novita AI: 本番環境向け外部KVキャッシュのためのPegaFlow

TL;DR

Novita AIとの提携により、PegaFlowはvLLMと統合されます。これはスタンドアロンのRustプロセスとして実装された外部KVキャッシュサービスであり、KVキャッシュのライフサイクルをvLLMワーカープロセスから分離し、ローカルインスタンスとリモートノード間でキャッシュをプールし、ピン留めされたホストメモリ、RDMAアクセス可能なリモートメモリ、およびSSDを組み合わせた3レベルのキャッシュ階層を実現します。

なぜKVキャッシュにプロセス境界が必要なのか

KVキャッシュは、本番環境のLLMサービングにおいて最もコストのかかるランタイム資産の一つです。多くの場合、ホストあたり数百GiBを占有し、割り当てとウォームアップに時間を要し、それを生成したリクエストパターンよりも長く生存します。 従来のインプロセス設計では、KVキャッシュは推論エンジンプロセスと密接に結合されています。そのため、エンジンがクラッシュしたり、ローリングアップグレードやモデルの切り替えを行ったりする際に、エンジンの再起動とともにホストのKVプールが消失してしまうため、問題が発生します。 PegaFlowは、KVキャッシュのランタイムを各マシンのスタンドアロンなデーモンに移動することでこの問題に対処します。このデーモンがホストKVプール、SSDキャッシュ、トポロジーメタデータ、RDMAリソース、インデックス状態、およびバックグラウンドタスクを所有し、vLLMワーカーはCUDA IPCおよびgRPCを通じて接続します。 この設計により、1つのキャッシュサーバーが同じホスト上の複数のエンジンと複数のモデルにサービスを提供できるようになり、同じメモリプール、SSD容量、およびノード間ネットワーク帯域幅を共有しながら、名前空間の分離を提供し、よりクリーンな障害ドメインを実現します。

外部キャッシュ所有による高速な再起動

ホストKVプールの所有権による起動パスへの影響を分離するために、TP8でQwen3-8Bを実行する8 x RTX 5090のセットアップを使用して、ダミーウェイトとeagerモードで測定を行いました。 組み込みのKVキャッシュ設計では、vLLMがready状態に達するまでに71.4秒かかりました。 PegaFlowを使用した場合、スタンドアロンサーバーが準備を整えた後、vLLMは33.2秒でready状態に達しました。これは、長寿命のホストキャッシュ割り当てを推論プロセスのライフサイクルから分離したことにより、起動パスが2.15倍高速化したことを示しています。

Rustデータパスとテールレイテンシの安定性

KVキャッシュを外部プロセスに移動した主な動機は、ライフサイクル管理、共有、およびCPUリソースの分離です。 このプロセスをRustで実装することで、Pythonインタープリタのオーバーヘッド、GILの競合、およびstop-the-worldのガベージコレクションを回避できます。これは、本番環境のキャッシュサービスが統計収集、インデックスアップロード、プリフェッチ、ヘルスチェック、メトリクス報告、エビクション、およびSSDキャッシュ管理などのバックグラウンドタスクを実行するため、非常に重要です。 PegaFlowでは、これらのタスクはvLLMとインタープリタランタイムを共有することなく、同じスタンドアロンRustサービス内で実行されるため、データプレーンのパスを妨げることなく、コントロールプレーンやメンテナンス作業を実行するための余裕がシステムに生まれます。

インスタンスとノード間でのキャッシュポーリング

本番環境のデプロイでは、プロセス、モデル、またはノードの境界によってキャッシュが互いに見えないため、同じ論理的KVコンテンツが何度も複製されることがよくあります。 PegaFlowは、これらの孤立したキャッシュの断片を共有キャッシュプールに変換します。 単一のホストでは、すべてのローカルインスタンスが同じPegaFlowサーバーに接続し、1つのCPU KVプールを共有します。 ホスト間では、PegaFlow MetaServerが近似的なグローバルインデックスを維持し、ノードが接続設定後のリモート側でのCPU関与ゼロのone-sided RDMA READを通じて、リモートKVブロックを取得できるようにします。

単一ノードのマルチインスタンス共有

同じ500 GiBのキャッシュ予算を持つ1つのホスト上で、8つのQwen3-8Bインスタンスを評価しました。

セットアップ キャッシュレイアウト スループット 平均TTFT リクエストヒット率
PegaFlow 500 GiB 共有プール 11.97 req/s 5.26 s 52.35%
In-process 8 x 62.5 GiB 孤立プール 7.68 req/s 8.22 s 11.77%
スループットは56%向上し、平均TTFTは36%低下し、リクエストヒット率は4.4倍に増加しました。

MLA論理的KVデデュープリケーション

また、500 GiBのキャッシュ予算の下で、TP8を使用したDeepSeek-V3.2 MLAを評価しました。

セットアップ キャッシュレイアウト スループット 平均TTFT リクエストヒット率
PegaFlow 論理的KVを1回のみ保存 1.81 req/s 35.66 s 97.23%
In-process TPランクごとにKVを保存 1.05 req/s 60.88 s 65.18%
スループットは72%向上し、平均TTFTは41%低下し、リクエストヒット率はトレースの実際的な上限に近づきました。

ノード間RDMA共有

ノードあたり8 x 400 Gbps RDMA NICを装備した内部本番推論クラスターにおいて、最近のオンラインリモートリードを数千件サンプリングしました。 少なくとも1 GiBの大きなプレフィックスプルについて、PegaFlowは本番トラフィック下で平均194 GB/sの実効スループットを維持し、P99は250 GB/s、ピークは261.6 GB/sに達しました。 この転送速度では、24 GiBのKVキャッシュセグメントをリモートノードから約100 msで取得でき、そうでなければ数秒のGPU時間を消費するであろうprefill計算を置き換えることができます。

3レベルのキャッシュ階層

ポーリングによりキャッシュ容量はより有用になりますが、ホストメモリは依然として有限です。 PegaFlowは、3レベルのキャッシュ階層でこれに対処します。ホットなローカルブロックはピン留めされたDRAMに保持され、リモートヒットはRDMA経由で取得でき、よりコールドな再利用可能なブロックはローカルSSDにスピルオーバー(退避)できます。

レベル メディア アクセスパス 一般的な役割
L1 ローカルピン留めDRAM ローカルメモリ 高速なローカルKV再利用
L2 リモートDRAM RDMA READ ノード間キャッシュ共有
L3 ローカルSSD io_uring 大容量スピルオーバー
SSDキャッシュはRustでio_uringの上に実装されています。内部テストでは、単一のSSDがピーク読み取りスループット約6.9 GB/sを達成し、PegaFlowはオンラインの定常状態のスループットをディスクあたり約6.5-6.6 GB/sに維持しました。
複数のディスクにわたるRAID0を使用すると、総スループットはほぼ線形にスケールします。
スキャンが多いワークロードやキャッシュ予算が少ないホストの場合、PegaFlowはTinyLFUアドミッションポリシーを有効にできます。これは、再利用される可能性が高いブロックのみを受け入れることで、一度限りのトラフィックからキャッシュを保護します。
TinyLFUは、最適なアドミッションポリシーはワークロードの形状に依存するため、デフォルトでは無効になっています。

理論的なヒット率の天井からの距離の測定

オンラインのヒット率だけでは誤解を招く可能性があります。 PegaFlowは、HyperLogLogを使用してオンラインで理論的なヒット率の上限を推定します:

r* = (N - U) / N

ここで、Nはウィンドウ内の全ブロックリクエスト数、Uは初めて見つかったユニークなブロック数です。 HyperLogLogにより、この推定は低コストに保たれます。24時間のウィンドウで、約0.8%の誤差で1 MiB未満のメモリしか使用しません。 PegaFlowは、デフォルトで15分、1時間、24時間のローリングHLLウィンドウをエクスポートします。 測定されたヒット率と理論的な上限を同じダッシュボードに配置することで、オペレーターは以下の3つのケースを区別できます:

  • キャッシュがすでにワークロードの天井に近いため、容量を追加してもあまり効果がない。
  • 測定されたヒット率が天井より大幅に低いため、容量、アドミッション、プリフェッチ、またはノード間ディスカバリを改善する余地がある。
  • 理論的な天井自体が低く、ワークロードの再利用性が限定的であり、ボトルネックは主にキャッシュの実装ではない。

外部コネクタを通じたvLLMとの統合

外部KVキャッシュシステムは、多くの場合、スケジューラ、ブロックマネージャー、またはアテンションカーネルへの侵襲的な変更を必要とします。 PegaFlowは代わりに、vLLMの外部KVコネクタメカニズムを通じて統合されます。 コネクタはkv_transfer_configを通じて設定され、外部パッケージはkv_connector_module_pathを使用して動的にロードできます。 これにより、vLLMのソースコードを修正したり、長期的なフォークを維持したりすることなく、実行時にPegaFlowが主要なKVキャッシュ操作を引き継ぐことができます。 vLLMの観点からは、PegaFlowはサービングエンジンの代替ではなく、KV転送インターフェースを介して接続された外部キャッシュバックエンドであり、vLLMは引き続きスケジューリング、モデル実行、バッチ処理、およびOpenAI互換のサービングパスを処理します。 この境界は両方のプロジェクトにとって有益です。PegaFlowは、Rustデータプレーン、SSDキャッシュ、RDMAパス、インデックス、およびコネクタロジックを独立して反復開発でき、vLLMは、外部キャッシュシステムに対して安定したコネクタ契約を公開しながら、コアサービングエンジンの改善を続けることができます。

クイックスタート

CUDAバージョンに応じたパッケージをインストールしてください:

uv pip install pegaflow-llm        # CUDA 12
uv pip install pegaflow-llm-cu13   # CUDA 13

ピン留めされたホストメモリとSSDキャッシュを備えた単一ノードのPegaFlowサーバーを起動します:

pegaflow-server \
  --pool-size 30gb \
  --ssd-cache-path <ssd-cache-file-path> \
  --ssd-cache-capacity 512gb

オンラインデプロイメントでは、--use-hugepagesを追加することをお勧めします。Huge pagesは事前に予約しておく必要があります。 マルチノードデプロイメントの場合は、まずMetaServerを起動し、次に各ノードでRDMA設定を使用してPegaFlowサーバーを起動します。 P2Pが有効な場合、他のノードがgRPCハンドシェイクとブロッククエリに使用するため、各PegaFlowサーバーの--addr0.0.0.0127.0.0.1ではなく、ルーティング可能なIPアドレスである必要があります。

pegaflow-metaserver --addr 0.0.0.0:50056
pegaflow-server \
  --addr this-node:50055 \
  --pool-size 30gb \
  --ssd-cache-path <ssd-cache-file-path> \
  --nics mlx5_0 mlx5_1 \
  --metaserver-addr http://metaserver-host:50056

vLLMのソースコードを修正せずにvLLMに接続します。この投稿の例では、vllm>=0.20.0を使用しています:

vllm serve <model> \
  --kv-transfer-config '{
    "kv_connector": "PegaKVConnector",
    "kv_role": "kv_both",
    "kv_connector_module_path": "pegaflow.connector"
  }'

環境変数PEGAFLOW_HOSTPEGAFLOW_PORTは、コネクタをPegaFlowサービスに向けます。デフォルトでは、http://127.0.0.150055です。

公開リファレンスベンチマーク

PegaFlowリポジトリには、Llama-3.1-8Bを使用したH800での公開KVキャッシュベンチマークも含まれています(8つのプロンプト、10Kトークンprefill、1トークンdecode、4.0 req/sを使用)。 そのセットアップでは、ウォームキャッシュパスにより、平均TTFTが572.5 msから61.5 msに、P99 TTFTが1113.7 msから77.0 msに減少しました。

PegaFlowを試す

PegaFlowはGitHubで利用可能です: novitalabs/pegaflow。リポジトリには、インストール手順、サーバー設定、P2P RDMA設定、メトリクスドキュメント、およびvLLMコネクタの例が含まれています。

謝辞

PegaFlowの構築と製品化に貢献してくれたNovita AIチーム、および、この統合を可能にした議論、レビュー、コネクタインフラストラクチャを提供してくれたvLLMメンテナーと広範なvLLMコミュニティに感謝いたします。

Sources

関連

  • Dispatch
  • Dispatch
  • Dispatch
  • Dispatch
  • Dispatch