概要
Nano-vLLMは、 LLM推論エンジン の本質を約1,200行のPythonで実装し、vLLMのコア設計を簡潔に理解可能。 プロンプトからトークン生成 までのアーキテクチャ・スケジューリング・リソース管理を解説。 バッチ処理やメモリ管理、スケジューラやBlock Managerの役割を詳細に説明。 Tensor ParallelismやCUDA Graph による高速化手法もカバー。 本記事はPart 1であり、モデル内部の詳細はPart 2で解説予定。
Nano-vLLMによるLLM推論エンジンのアーキテクチャ
- LLM APIの裏側 には、OpenAIやClaude、DeepSeekなどが利用する推論エンジンの存在
- Nano-vLLMは、 vLLMの本質機能 (プレフィックスキャッシュ、テンソル並列、CUDAグラフ、torch最適化)を簡潔に実装
- ベンチマークで 本家vLLMと同等以上のスループット を実現
- 高レベルAPIからは隠蔽 されている内部処理を可視化
プロンプトからシーケンスへの変換
- generateメソッドにより、 プロンプトとパラメータを入力 し、生成文を受け取る
- トークナイザ がプロンプトをトークンへ分割し、シーケンス(可変長トークンID配列)へ変換
- モデルごとに トークナイザ仕様が異なる ため、同じ長さのプロンプトでもトークン数が異なる場合あり
プロデューサ・コンシューマパターンとスケジューラ
- add_requestメソッドが プロンプトをシーケンス化し、スケジューラのキューに投入
- 別スレッドのstepループが バッチ単位でシーケンスを取り出し処理
- バッチ処理によりGPUオーバーヘッドを分散し、スループット向上
- バッチサイズの調整により スループットとレイテンシのトレードオフ を制御
プレフィルとデコードの2フェーズ
- プレフィル :プロンプト全体を一括処理し、内部状態を構築
- デコード :1トークンずつ生成し、ユーザーにストリーミング表示
- スケジューラは 各シーケンスのフェーズを区別 し、適切にバッチ化
スケジューラ内部の仕組み
- Waiting Queue :未処理シーケンスの待機列
- Running Queue :処理中シーケンスの実行列
- Block Managerと連携し、 リソース割当てや解放を管理
- GPUメモリ(KVキャッシュ)が枯渇した場合、 シーケンスを一時停止し再待機
Block ManagerによるKVキャッシュ管理
- シーケンスを 固定長ブロック(デフォルト256トークン) に分割
- ブロックごとにハッシュ管理 し、同一内容は参照カウントで再利用(プレフィックスキャッシュ)
- Block Managerは CPU側でメタデータのみ管理 し、実データはGPUメモリ上に配置(制御プレーンとデータプレーンの分離)
- ブロック解放時は 即座に再利用可能マーク し、ゼロクリアせず上書き
モデルランナーと並列実行
- Model Runnerがバッチを受け取り、GPU上で実行
- テンソル並列(TP) により複数GPUで分散処理
- Rank 0(リーダー)がコマンド発行・調整
- Rank 1~N-1(ワーカー)が共有メモリ経由で命令を受信・実行
- シングルマシン内のマルチGPU構成 に最適化
計算準備とCUDA Graph
- プレフィル時は 可変長シーケンスをバッチ化
- デコード時は 1トークンずつバッチ化し、位置・スロット情報付与
- CPUトークンデータをGPUテンソル化 し、転送
- CUDA Graph でカーネル起動オーバーヘッドを削減
- 主なバッチサイズごとにグラフを事前キャプチャ
- デコード処理を高速化
サンプリングと温度パラメータ
- モデル出力は 語彙全体のロジット分布
- サンプリング工程 で1トークン選択
- 温度パラメータ で確率分布の鋭さを制御
- 低温度:決定的・集中した出力
- 高温度:多様・創造的な出力
Part 2への予告
- モデル内部の トークン変換・アテンション機構・KVキャッシュ物理配置
- Dense/MoEアーキテクチャ の違い
- 計算レベルのテンソル並列 の詳細
- プロンプトから生成文までの 全体像の完成