世界を動かす技術を、日本語で。

Nano-vLLM: vLLMスタイルの推論エンジンの仕組み

概要

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アーキテクチャ の違い
  • 計算レベルのテンソル並列 の詳細
  • プロンプトから生成文までの 全体像の完成

Hackerたちの意見

なんか全体的にAIが書いたみたいに感じるな、コードベースから生成されたっていうか。* *著者の返答によるとこれは間違いらしい、ごめんね。例えば、(nano)vLLMの内部に触れてるけど、PagedAttentionについては一度も言及されてないんだよね(vLLMの基本的なアイデアの一つなのに)。それに、パート2では密なモデルとMoEについて触れるって言ってるけど、nanovllmはソースに密なQwen3をハードコーディングしてるから、ちょっと変だよね。vLLMの仕組みについてのもっと良い(と思う)解説がここにあるよ:- https://hamzaelshafie.bearblog.dev/paged-attention-from-firs... - https://www.aleksagordic.com/blog/vllm - https://huggingface.co/blog/continuous_batching アレクサのブログはちょっと難しいけど、読む価値はあるよ。vLLMの魔法の多くはPagedAttentionのカーネルで起こってて、nanovllmにすごく簡潔に実装されてるんだ。そして、コードベース自体も素晴らしくて読みやすいよ! — 1. https://arxiv.org/abs/2309.06180

PagedAttentionのカーネルにはあんまり関係ないよ。PagedAttentionはFlashAttentionに統合されてて、FlashAttentionのカーネルはプレフィルとデコーディングの両方でpaged KVを使えるようになってる。paged attention専用のカーネルはKVブロックのコピー用だけ(デバイス間、デバイスからホスト、ホストからデバイス)だよ。少なくともFA2とFA3では、vLLMはpaged attentionのパッチを持ったFAのフォークを維持してた。

こんにちは、jbarrow。フィードバックとリンクをありがとう!すごく良い読み物だったよ(他の人にも多分役立つと思う)。それはさておき、はっきりさせておきたいことがあるんだ:内容はAIによって書かれたわけじゃなくて、一度にデータベースから生成されたわけでもないよ。もし、私が書いたものを生み出せるエージェントやプロンプトがあるなら、ぜひ教えてほしいな。それがあれば、2つの週末を節約できたかも :) 質問に答える前に、少し背景を説明するね:私はMLのバックグラウンドはないけど、クラウドインフラの経験はたくさんある開発者なんだ。今、オープンソースのAIインフラプロジェクトを作ってるから、nano-vllmを勉強したんだ。だから、私の文章にはMLの知識にギャップがあるかもしれない。具体的なポイントについて:> (nano)vLLMの内部に触れていて、PagedAttentionについては一度も言及していない っていうのは、nano-vllmで「paged attention」という名前を見つけられなかったからだよ。あなたがリンクしてくれた最初の記事を読んで、特に「Paged KV Caching」のセクションを見たら、ブロック管理ロジックとCPU/GPUブロックマッピングが私が両方の投稿でカバーした内容とまさに一致してると思ったんだ。paged attentionの全体像ではないかもしれないけど、コードで見たことを解釈して、核心的なアイデアを捉えたと思う。それは合理的な結果だと思うよ。> パート2では密なモデルとMoEについて触れるって言ってるけど、nanovllmはソースに密なQwen3をハードコーディングしてる これは私の学び方と背景を反映してるね。ポイント1と同じで、ブロックデザインが有名なPagedAttentionの実装だとは気づかなかったから、そう名付けなかったんだ。ポイント2については、密なQwen3を見て、Hugging Faceで見たxx-B-A-yy-B MoEモデルとどう違うのか気になったんだ—特にデコーダーレイヤーで何が変わるのか。そんな好奇心からMoEについて学んで、同じ疑問を持つ他の人のために書いたんだ。--- この時代に、人々が読んでいるものがAI生成かどうかを気にするのは理解できるよ。誰も人間が関与していない低労力のものに時間を無駄にしたくないからね。でも、上で説明したように、そして私の手描きのExcalidrawの図が示すように(私が満足できる論理の図を生成するLLMは見たことがない)、これは私自身の知識の背景と好みによって形作られた学びの結果なんだ。

実際、これはAIが今の時点でできない明瞭さ、焦点、言葉の経済性の素晴らしい例だと思ったよ。

HNは一回の投稿でリンクを一つしか許可してないから、ここにパート2を落としておくね。https://www.neutree.ai/blog/nano-vllm-part-2

素晴らしい仕事だね!これはすべての複雑なシステムに必要なプロジェクトだと思う。vLLMのコードベースみたいなシステムは巨大で追いかけるのが難しいから、他のインフラ(nano-Kubernetesやnano Postgres…)でも同じアプローチを見てみたいな。

私の構造化されたLLM出力ハンドブックの宣伝をさせてね、これは似たような精神で書かれてるよ: https://nanonets.com/cookbooks/structured-llm-outputs/