LLM 自ホストで数百万円節約する方法
Cline Blog は、Kimi K2.6 モデルを例に挙げ、オープンウェイト LLM の自己ホスティングにおけるメモリ要件、GPU 選定、およびコスト計算の具体的な数学的根拠と経済性を詳述し、エンジニアや経営層が意思決定を行うための実践的なガイドを提供している。
キーポイント
LLM インフラのコスト計算モデルの解明
記事は LLM の推論コストとメモリ要件を数式で明確化し、オープンウェイト モデルがなぜ経済的に有利になり得るかを「ドル」単位で説明している。
Kimi K2.6 のアーキテクチャ分析
DeepSeek V3 にインスパイアされた MoE(Mixture of Experts)構造を持つ Kimi K2.6 を具体例として、1 兆パラメータ・320 億アクティブパラメータという構成の詳細を解説している。
GPU ハードウェア選定の指針
NVIDIA B200(Blackwell)の VRAM や NVLink を用いた GPU クラスター構成など、自己ホスティングに適したハードウェア選定の実践的な基準を提示している。
多様な読者層への対応
ソフトウェアエンジニアから経営層、学生まで対象とし、数学的詳細と経済的結論の両方をバランスよく提供し、それぞれの立場で活用できる構成になっている。
固定コストとスケーラビリティ
1 ノードあたりの時間あたり$48という固定コストは利用ユーザー数に関わらず一定であり、真のトークン単価を決定するのはこのコストからいかに多くのトークンを抽出できるかである。
自己ホストの経済的閾値
自己ホストが経済的に成立するのは月間$35,000以上のAPI推論費用がかかっている場合に限られ、これはモデルをロードするための最小構成要件でもある。
FP4量子化によるコスト削減
1兆パラメータのモデルをNVFP4(0.5バイト/パラメータ)で量子化することで500GBのメモリでロード可能となり、3枚のB200 GPUで動作するが、これは品質と価格のトレードオフである。
重要な引用
If you believe that cheap open weight models are the future then this blog is for you, we all know the why, but I will show you the how grounded in the economics behind it.
This is a single and arguably the only post that covers both the math of LLM inference and the dollars, grounded in production traffic and real numbers from inference provider negotiations.
"Serving 1 user or 1,000, the meter runs the same. The rest of this blog is about squeezing as many tokens as possible out of that $48/hour as that's what sets your real $/token."
"Self-hosting only makes sense if you're already spending $35K+/month on API inference for this model."
The only way to know what you're shipping is to run evals.
Max output speed is just bandwidth ÷ bytes_per_token.
影響分析・編集コメントを表示
影響分析
この記事は、LLM の運用コストが大きな課題となっている現在、技術者だけでなく意思決定者にも「自己ホスティング」の実現可能性と経済的メリットを定量的に示す重要な役割を果たします。特に、抽象的な議論ではなく具体的な数式とハードウェア仕様に基づいた分析は、企業が AI 導入戦略を見直す際の強力な根拠となり得ます。
編集コメント
本記事は、LLM の自己ホスティングに関する一般的な議論を脱却し、具体的な数学的根拠と経済計算に基づいた極めて実用的なガイドとなっています。特に、経営層が技術的な詳細に立ち入らずとも意思決定できる構成は、組織内の AI 導入プロセスにおいて非常に価値が高いと言えます。
はじめに

安価なオープンウェイトモデルが未来だと信じるなら、この記事はあなた向けです。なぜそう言えるのかは既にご存知でしょうから、ここではその根拠となる経済性に基づいた具体的な「やり方」をお伝えします。
私はこれまで、この形式で LLM の推論に関する数式とコスト計算の両方を、実際の運用トラフィックやプロバイダーとの交渉データに基づいて解説した記事を見つけたことがありません。これは、LLM 推論の数式とドル単位の費用を、生産環境での実数値に裏打ちされて初めてカバーできる、唯一無二(あるいは最も重要な)記事です。
もし本書の数式計算に誤りが見つかった場合は、印刷版の書籍をお送りし、末尾のクレジット欄にお名前を記載させていただきます。
この記事は誰向け?
- ソフトウェアエンジニア・マネージャー: オープンウェイトモデルを実装する方
- AI 研究・推論エンジニア: 推論の数式と価格設定の実用的なモデルを知りたい方
- 経営層・プロダクトマネージャー: 「自社ホスト化(Self-hosting)に価値があるのか」を検討中の方。数式の部分はざっと読み飛ばし、末尾の金額部分だけ読んで判断してください。
- 学生: フロンティアラボでの就職を目指す方
このブログ記事に必要な数学は高校レベルの代数だけです。登場するすべての式は、掛け算・割り算・累乗などの基本演算で構成されています。機械学習の深い専門知識は必須ではありません。トランスフォーマー、MoE(Mixture of Experts)、KV キャッシュ、量子化などに関する用語は、本文内で解説するか、私が探した最も優れた入門記事へのリンクを貼っています。ただし、このブログ記事自体は非常に密度が高く、真に理解を深めるには、これらのリンク先でさらに深く学ぶ必要があります。最低限でも、内容を完全に自分のものにするためには週末 1 日を費やすことをお勧めします。
では、具体的に何を取り扱うのでしょうか?
今回の事例として取り上げるのは「Kimi K2.6」です。これの性能評価には、Cline の実際の生産環境でのトラフィックデータを基準(グランドトゥルース)とします。この計算式は、自分で GPU を借りる場合も、推論プロバイダーから利用する場合も、どちらでも通用するものです。順を追って、モデルの読み込み、推論サービスの提供、バッチ処理、そして本番環境向けにチューニングする方法まで解説していきます。
モデルアーキテクチャ
モデルをセルフホストするには、まずその重み(ウェイト)を GPU にロードする必要があります。これに必要なメモリ量は、モデルのアーキテクチャによって決まります。Kimi K2.6 は DeepSeek V3 のアーキテクチャに着想を得たもので、MoE パラメータを採用しています。
- 総パラメータ数:1 兆(スパース MoE)
- アクティブパラメータ数:320 億
- ヒドゥンサイズ:7,168
- アテンションヘッド数:64
- ルートされるエキスパート数:384
- 共有エキスパート数:1
- トークンあたりのエキスパート数:8
- MoE インターミディエイトサイズ:2,048
- MoE レイヤーの頻度:1
- コンテキストウィンドウ:256K トークン
これらの数値をゼロから導出したい場合は、Kipply の伝説的な「パラメータ計測記事」をお読みください。
トランスフォーマーアーキテクチャの背景知識を得たいなら、必ず『The Illustrated Transformer』を読んでください。もしブログ記事を読む気力がない場合は、私がこれまで見た中で最も優れた LLM 可視化ツールである「LLM Visualizer」を試してみてください。
GPU の選定
今回は NVIDIA B200(Blackwell)を採用します。これは NVIDIA のフラッグシップ推論用 GPU で、主要なネオクラウドからレンタル可能です。
この GPU について知っておくべきポイントは以下の通りです。
- GPU 1 基あたり 192 GB の HBM3e VRAM を搭載
- 標準的な HGX ラックには 8 基の GPU が NVLink で接続されています。NVLink は GPU 間の高速インターコネクトであり、これにより 8 基の GPU が推論時にあたかも巨大な 1 つの GPU のように動作します。
- 8 基構成のノードにおける総 GPU メモリ容量は 192 GB × 8 = 1,536 GB(約 1.5 TB)です。
このノードの実質的なコストはいくらになるのでしょうか?
本ブログ全体で統一する数値を一つ決めておきましょう。GPU 1 基あたり時間当たり 6 ドルとします。2026 年の実際の B200 の価格は、GPU 単体のレンタルであれば約 4 ドルに近くなる可能性がありますが、ここでは保守的な上限として切り上げました。もしこの計算で採算が取れるなら、現実世界でも問題なく成立するはずです。
- $6/GPU/時間 × 8 GPU = 1 ノードあたり 時間当たり $48
- $48 × 24 時間 = 1 ノードあたり 1 日当たり $1,152
- $48 × 730 時間(月平均)= 1 ノードあたり 1 ヶ月当たり $35,040
- $48 × 8,760 時間 = 1 ノードあたり 1 年当たり $420,480
この時間当たり$48 が固定費です。ユーザーが 1 人でも 1,000 人でも、メーターは同じように回ります。本ブログの残りの部分では、この「時間当たり$48」からいかに多くのトークンを引き出すかについて解説します。これが実質的なトークンあたりのコストを決めるからです。
注記:
このモデルを API 推論に月額 35,000 ドル以上使っている場合のみ、セルフホスティングは意味を持ちます。このモデルは小規模な構成では動作しないため、月額 35,000 ドルが最低限の参入条件となります。
GPU のレンタルなら月額 3.5〜4 ドルから可能ですが、推論プロバイダーを利用すると、モデルのホスティングやスペキュレーティブ・ディコーディング(予測的デコーディング)、そしてその他の推論最適化技術の管理コストとして、月額 5.5〜6 ドルを請求されます。このブログ記事の後半で詳しく解説しますが、他人にモデルを任せるために追加費用を支払うのは、適切に行えば推論エンジニアを雇うよりもはるかに安く、非常に優れた選択肢です。
では、このモデルを読み込むには何枚の GPU が必要なのでしょうか?
まず重み(ウェイト)のサイズを確認しましょう。
Kimi K2.6 は 1 トリオン(10 兆)のパラメータを持っています。今回は FP4 量子化(パラメータあたり 0.5 バイト)で動作させます。量子化とは、モデル内の各重みをより少ないビット数で保存する技術です。例えば $4.7283910 を四捨五入して $5 に丸めるようなものです。これによりメモリ上のモデルサイズが劇的に縮小され、注意深く実施すれば、ほぼ同じ精度の回答を得ることができます。
FP4 は積極的な量子化レベルですが、現代のモデルは量子化を前提として訓練されているため、品質への悪影響はさほど大きくありません。また、ホスティングが容易になり、GPU への読み込みに必要なメモリも大幅に削減されます。
計算式:
重みサイズ = 1,000,000,000,000 パラメータ × 0.5 バイト = 500 GB
次に GPU メモリで割ります。
500 GB ÷ B200 のメモリ 192 GB = 約 2.60
つまり、技術的には FP4 量子化モデルの重みをロードするには B200 が 3 枚あれば十分です。これが最低ラインであり、VRAM にモデルを読み込むにはこれで足りるものの、それ以上の余裕はありません。
量子化と品質について
量子化は、コストと品質のトレードオフです。コスト面では、このセクション以降の数値すべてがパラメータあたりのバイト数に対して線形に比例します。FP4 では重みが 500GB になり、FP8 にするとその倍の 1TB(B200 を 3 基ではなく 6 基必要とします)、BF16 にするとさらに倍になります。現代の量子化対応モデルにおいて、許容できる品質を維持しつつ最も安価な tier が FP4 です。そのため私たちはこれを採用しています。もし評価結果で FP4 がワークロードに悪影響を与えていると判明すれば、計算式はそのままに FP8 で再構築すればよいだけです(コストは上がりますが)。なお、ここで言う「FP4」とは Blackwell のネイティブな 4 ビット形式である NVFP4 を指します。以降のブログ全体でも簡略化のため「FP4」という表記を使います。
品質面でのトレードオフは、スペックシートからは見えません。一部のプロバイダーは低コスト・低遅延の推論を提供していますが、量子化が過度に激しすぎて、どれだけ優れたレイテンシ SLA(Service Level Agreement)を謳っていても出力が崩壊してしまいます。実際に何が提供されているかを知る唯一の方法は、評価(evals)を実行することです(当社の設定はこちら)。
このモデルを提供するために必要な GPU 数は?
モデルを読み込むことと、実際のトラフィックに対応してサービスを提供することは別問題であり、後者の方がより多くの VRAM を消費します。同時接続するユーザーそれぞれに、KV キャッシュの断片(アテンションが二次関数的になるのを防ぎ、新しい推論リクエストでキャッシュを活用するための per-user memory)が必要です。また、リクエストを効率的にバッチ処理するために帯域幅と余裕分も確保する必要があります。KV キャッシュ、帯域幅、そして余裕分については次節で詳しく解説しますが、現時点では VRAM の残りがここに使われると理解してください。
さて、8 枚の B200 GPU を搭載したノード全体(VRAM 合計 1,536 GB)を活用します。このリソース配分は以下の通りです。
| 項目 | 計算式 | メモリ使用量 | 残容量 |
|---|---|---|---|
| ノードの総 VRAM | 192 GB × 8 GPU | — | 1,536 GB |
| モデル重み (Weights) | 1T パラメータ × 0.5 バイト | 500 GB | 1,036 GB |
| アクティベーション (推論中の作業用メモリ) | ~80 GB | 956 GB | — |
| KV キャッシュ用 (=同時利用可能ユーザー数) | ~956 GB | — | — |
この約 956 GB が、実際にユーザーにサービスを提供するための予算です。次のセクションでは、このリソースをどのように配分するかを解説します。

モデルの提供 (Serving the model)
リクエストが来ると、モデルはまずプロンプト全体を読み込む「プリフィル」処理を行い、その後トークンを一つずつ生成する「デコード」処理を行います。今回は、長文生成においてコストの大部分を占めるデコードから解説し、後ほどプリフィルについても触れます。
デコードの要点 (TL;DR)
LLM は一度に一つのトークンだけを生成します。モデルは新しいトークンを出力する際、これまでに得られたすべての情報(入力プロンプトと、直前に生成したトークン)を参照して次のトークンを決定し、処理が完了するまでこれを繰り返します。
[prompt] → token_1
[prompt + token_1] → token_2
[prompt + token_1 + token_2] → token_3
...
このループの 1 回(1 フォワードパス)ごとに、入力は数十層のネットワークを通過します。各層は VRAM から自身の重みスライスを読み取り、その出力を次の層へ渡していきます。最終的に、次に来るトークンの確率分布が得られ、モデルはその中から一つを選択して生成し、また次のステップへと進みます。
つまり、推論処理とは「VRAM から重みを読み込む → 行列計算を行う → トークンを出力する → これを繰り返す」という単純なループに過ぎません。
トークンの生成(デコード)
320 億のアクティブパラメータを持つモデルにおいて、出力トークンを 1 つ生成する際に必要なデータフローは以下の通りです(FP4 量子化では 1 パラメータあたり 0.5 バイトとなります)。
トークンあたりの読み込みバイト数 = 32B アクティブ × 0.5 バイト = 16GB
つまり、生成するトークン 1 つごとに、重みデータ 16GB が帯域幅を流れます。これが最大のボトルネックとなる数値です。
NVIDIA B200 GPU 1 基あたりのメモリ帯域幅は 8TB/s です。一見すると莫大な数字に見えますが、計算を実行してみましょう。最大出力速度は「帯域幅 ÷ トークンあたりのバイト数」で求められます。
- 単一の B200: 8 TB/s
- 8 GPU ノード(理論値): 64 TB/s
- 8 GPU ノード(実効値): 同期オーバーヘッドを考慮して約 50 TB/s
50,000 GB/s ÷ 16 GB/token ≈ 3,125 tok/s(理論値)
実際の運用ではメモリ帯域利用率(MBU)が 10〜12% に制限されるため、実効的なデコード速度は合計で約 312〜375 トークン/秒となります。
つまり、FP4 で量子化された Kimi K2.6 を 8 GPU の B200 ノード全体で小バッチサイズで処理する場合、理論上の上限は aggregate decode(集計デコード)速度で約 3,125 トークン/秒です。
デコードは逐次処理のため、トークン N+1 を生成するにはトークン N の完了を待たなければなりません。このため、デコードは帯域幅に依存し、出力ストリームの速度を決める指標が TPS(1 秒あたりのトークン数)となります。(注:スペキュレーティブ・ディコーディングの例外を除く)
理論上の最大デコードスループットと実測値の最大スループットの注意点
上記の「16 GB/token」という数字は、バッチサイズが 1 の場合、つまり各トークンが独自に専門家(エキスパート)を呼び出すという前提に基づいています。しかし、バッチ処理が始まるとこの前提は崩れます。多くのユーザーが同じ順次計算パス(フォワードパス)を通るようになると、MoE(Mixture of Experts)構造内でトークン間で専門家の読み込みが共有されるため、1 トークンあたりの実効バイト数は減少し、デコード全体の処理速度はこの数値を大きく上回ります。他にも考慮すべき要素はありますが、バッチ処理の具体的な仕組みについては後述する「バッチング」のセクションで詳しく解説します。
「3,125 tok/s」という数字も理論上の値に過ぎません。実際に達成できる性能は、MBU(Memory Bandwidth Utilization:メモリ帯域利用率)によって決まります。これは、推論スタックが実質的に有効な作業に割り当てている、名目上の帯域幅の割合のことです。この MBU の値は状況によって大きく変動します。例えば、vLLM と Kimi K2.6 を使用し、8 枚の B200 GPU に 80K トークンのコンテキストを処理させた場合など、下限に近い環境では約 11% という測定結果も出ています。
私たちが得られる実践的な教訓は、理論上の上限やベンダーが提示する数値を鵜呑みにしてはいけないということです。負荷テストを実施し、以下の式で実際に達成された MBU を計算してみましょう。
(測定した Aggregate Decode の tok/s × 1 トークンあたりのバイト数)÷ ノードの名目帯域幅
その後、研究論文などと照合して、自分の結果が妥当な範囲内にあるか確認してください。もし大幅に外れている場合は、その原因を突き止める必要があります。
さらに進む前に、GPU の推論性能における真のボトルネックを理解するための 2 つの重要な概念を押さえておく必要があります。
- メモリバウンドとコンピュートバウンドの違い
- 演算強度(Arithmetic Intensity)
メモリバウンドとコンピュートバウンド
これはトランスフォーマー推論、より広くは深層学習の最適化において頻繁に遭遇する課題です。基本的な考え方は以下の通りです。GPU で数値計算を行うには、まずメモリから重み(weights)を読み出す必要があり、これがメモリー帯域幅の消費につながります。
好消息として、この部分は非常に最適化されており、GPU は最初の重みがメモリから読み込まれた瞬間に計算を開始できます。つまり、メモリの読み込みと数学演算は並列して実行されるのです。
したがって、ある瞬間には以下の 2 つの状態のいずれかが起こっています。
Compute-bound(計算バウンド)/ Flop-bound: この場合、GPU は演算処理でボトルネックになっています。演算ユニットがフル稼働しており、メモリはアイドル状態です。FLOP(Floating Point Operation)とは浮動小数点演算の 1 つを指します。乗算 1 回、加算 1 回などが該当します。「GPU は 15 PFLOPS の性能を持つ」と言う場合、それは 1 秒間に 15 × 10¹⁵回の浮動小数点演算が可能であることを意味します。計算バウンドと FLOP バウンドの詳細については、講義ノートをご覧ください。
Memory-bound(メモリーバウンド): この場合、メモリへのデータ転送経路がフル稼働しており、演算ユニットはアイドル状態です。
もう一度強調しておきますが、デコード処理はメモリー帯域幅に依存しており、これが推論速度の大きなボトルネックとなっています。
演算強度(Arithmetic Intensity)
GPU は常に「メモリーバウンド」か「計算バウンド」のいずれかの状態にあります。この 2 つの状態を切り替えるのが「演算強度」です。これは、メモリから読み込んだ 1 バイトあたりに行われる FLOP の数で定義されます。
arithmetic_intensity = 実行された FLOPs / HBM から読み込まれたバイト数
すべての GPU には、計算処理と帯域幅処理が同時に完了する「ブレイクイブンポイント(屋根モデルにおける山頂)」が存在します。この山頂より下側ではメモリーバウンドとなり、上側では計算バウンドとなります。
FP4 で動作する B200 の場合、計算とメモリのバランスを示す「リッジ(山頂)」は以下のようになります。
ridge = peak_flops / peak_bandwidth
= 10 PFLOPS / 8 TB/s
≈ 1,250 FLOPs per byte
つまり B200 では、計算がボトルネックになる前に、重み(weight)の 1 バイトあたり約 1,250 回の演算を行う必要があります。これ未満だと、数学演算ユニットが HBM のデータ転送を待ってアイドル状態になってしまいます。
ここでデコードとプリフィルの位置づけを確認しましょう。
デコード(バッチサイズ=1):読み込んだ重み 1 バイトあたり約 2 FLOPs(各重み値に対して乗算・加算が 1 回ずつ)。これは完全にメモリ帯域制限領域にあり、リッジから約 600 倍も低い位置にあります。そのため、デコード時のトークン生成速度(tok/s)は演算能力ではなく、帯域幅によって決定されます(以前にも触れましたね)。
プリフィル:重みは一度だけ読み込まれ、数千のトークン(またはバッチ処理)で再利用されます。このとき、その読み込みを共有するトークン数に応じて演算強度はほぼ線形に増加します。十分な数のトークンを 1 つの順伝播パスに通せば、リッジを超えて計算制限領域へと移行できます。
この視点は、本ブログの残りの部分でも常に意識しておくべきポイントです。後述するすべての最適化手法は、根底では「HBM のトラフィックにおける 1 バイトあたりにより多くの有用なトークンを生成させる」ための工夫、つまり演算強度を高めるトリックにほかなりません。後ほど負荷テストを行い GPU への負荷を高めた際、この両方の限界を実践で確認できるでしょう。
プロンプトトークンの読み込み(プリフィル)
次に学ぶべき概念は「プリフィル」です。これは、ユーザーが入力したプロンプト全体を一度に大規模な並列行列乗算として読み込み、モデルがそれを処理して応答(デコード)を生成できるようにするプロセスを指します。
imageイラスト付きトランスフォーマーの画像
なぜプリフィル(初期処理)を並列実行できるのか?
入力シーケンス全体が既知であるため、データを層に流し込む際に並列処理が可能です。重みの読み出しは 1 回で済み、その瞬間に数千トークンを同時に処理できます。このように 1 回の読み出しを数千トークンで共有することで、帯域幅のボトルネックは解消されます。
プリフィルは計算量(コンピュート)がボトルネックとなります。今回のケースでは、B200 GPU は帯域幅よりも圧倒的に高い計算能力を持っています。GPU 1 基あたり FP4 で約 10 PFLOPS の密集演算性能があり、8 基を並列運用しています。
現実的なプリフィル速度は、8 GPU 構成の B200 ノードで集計すると約 78,000 トークン/秒に達します。これは、長い Kimi K2.6 の会話において、1 秒間に 1 つのコーディングエージェント相当の新しいプロンプトを処理できる速度です。Cline でこのワークロードを実行した際に測定される値がこれになります。
計算の詳細
GPU あたりの FLOPS = 10 PFLOPS
トークンあたりの FLOPS = 2 × 32B(アクティブ)= 64 GFLOPs
ノードの計算能力 = 8 GPU × 10 PFLOPS = 80 PFLOPS(密な FP4 演算)
理論上の最大値 = 80 PFLOPS ÷ 64 GFLOPs ≈ 125 万 トークン/秒
現実的な数値 ≈ 6.4% の MFU(アテンションの二次関数的コストと MoE のオール・トゥー・オール通信がボトルネック。ただし B200 のアテンションパイプラインが部分的にこれを相殺)
≈ 長いプロンプトで 78,000 トークン/秒(負荷テストで実際に観測された値)
MFU(Model FLOPS Utilization:モデルの FLOPS 利用率)は、モデル処理で実際に消費された FLOPs/秒を、ハードウェアが持つピーク FLOPs/秒で割った値です。
これは事前計算(prefill)の数値に対する現実的なチェックになります。もし測定した MFU が文献で報告されている範囲から大きく外れているなら、自社のスタックに根本的な問題があるか、あるいは他社の方が同じハードウェアからより多くの性能を引き出しているかのどちらかです。
TTFT:最初のトークンまでの時間(Time To First Token)
これは、チャットで「送信」ボタンを押してから最初の文字がストリーミング表示されるまでにかかる待ち時間を指す指標 TTFT の由来です。最初のトークンが表示されるまでの間はすべて計算リソースを消費する事前計算(prefill)の領域であり、それ以降はメモリ帯域幅を消費するデコードの領域となります。
もしノードで 80,000 トークン/秒の速度で事前計算が行える場合でも、ユーザーが 80,000 トークンのプロンプトを送ってきたとすると:
80,000 トークン ÷ 80,000 トークン/秒 = TTFT は 1 秒
ただし実際には、以下の 2 つの要因が異なる方向にこの数値を大きく変動させます:
- バッチ処理:80K トークン/秒という数値は、GPU ノード全体の最大スループットです。もし 16 ユーザーが同時にプリフィル(初期化)を実行した場合、各ユーザーに割り当てられる実効スループットは約 5,000 トークン/秒に過ぎません。その結果、80K のプロンプト処理には約 16 秒かかってしまいます。
ストリームごとの数値と集計値では大きく異なり、実際の性能を把握するにはさまざまな構成で負荷テストを行う必要があります。バッチ処理の詳細については、このドキュメントの後半で改めて解説します。
- KV キャッシュの活用とプロンプトの再利用:コーディングエージェントやチャットボットでは、会話が積み重なるように進行します。長いスレッド内で 5 通目のメッセージが送信された際、過去の会話から得た KV キャッシュはすでに VRAM に保持されているため、80K のコンテキスト全体を再プリフィルする必要はありません。
必要なのは差分のみです。つまり、新しいユーザーのメッセージと、その時点で読み込まれた最新の文脈(ファイルの読み込みやツールの出力など)だけです。
Cline ではシステムプロンプトは小さく、約 3〜4K トークン程度です。トークンの大半を占めるのは、会話のやり取りの中で行われるファイル読み込みや検索の結果です。コンテキスト全体が 80K に達していても、実際のある特定のターンでプリフィルされる新しいトークンは通常 8〜10K 程度であり、その多くはファイル読み込みによるものです。
KV キャッシュ:956 GB の VRAM はどこへ消えたのか
先ほど「約 956 GB の空き VRAM を確保した」とお話ししましたが、これがまさに KV キャッシュに充当される場所です。
KV キャッシュが解決する核心的な問題はこれです。モデルが新しいトークンを 1 つデコードするたびに、アテンション層はコンテキスト内のすべての過去トークンの K(キー)と V(バリュー)ベクトルを必要とします。キャッシュがない場合、各デコードステップで K と V を最初から再計算することになり、新しいトークンごとに履歴全体を新規に事前処理(prefill)する羽目になります。これは何の価値もない二乗計算です。
解決策はシンプルです。過去のトークンからの K と V は、そのトークンの決定論的な関数であり、モデルの重みも変化しません。つまり、ステップ 5 で計算した K と V の値は、ステップ 6、7、10 でも全く同じ数字として再計算されることになります。一度計算して VRAM に保存し、その後のすべてのステップで読み出せばよいのです。

上記の画像が、この仕組みの直感的な理解を助けます。
洞察 2:次のトークンのアテンション計算には、新しいトークンからのクエリベクトルと、すべての過去のキー・バリューベクトルだけで十分です。Q(クエリ)はステップごとに新しく生成されますが、過去のステップから得た K と V は、一度計算すれば永遠に再利用可能です。

つまり、キャッシュの動作は以下のようになります。トークン 5 を生成する際、K_5 と V_5 を新たに作成して K/V バッファに追加します。一方、トークン 1~4 はキャッシュから読み出されます。次にトークン 6 を処理する際は、K_6 と V_6 を追加し、トークン 1~5 をキャッシュから取得します。ステップごとに新しいペアを 1 つずつ追加するだけで、再計算は不要です。これが KV キャッシュのすべてです。
このキャッシュのサイズは、何バイトになるのでしょうか?
DeepSeek V3 と、アテンションアーキテクチャを継承する Kimi は、MLA(Multi-head Latent Attention)を採用しています。従来のように各ヘッドごとに K(Key)と V(Value)をキャッシュするのではなく、MLA では層ごとに単一の共有潜在ベクトルと小さな RoPE 成分に圧縮します。これにより、キャッシュサイズはヘッド数に依存しなくなります。
bytes_per_token (MLA) = num_layers × (kv_lora_rank + qk_rope_head_dim) × bytes_per_value
= 61 × (512 + 64) × 1
≈ 35 KB / token / user
956 GB の VRAM をキャッシュに充てる場合、ユーザーあたりの KV キャッシュ量は以下のようになります。
KV per user = 35 KB × context_length
利用可能な VRAM は 956 GB なので、理論上の最大同時接続ユーザー数は以下で計算できます。
max_users ≈ 956 GB / (context_length × 35 KB)
| コンテキスト長 | ユーザーあたりの KV キャッシュ量 | 理論上の最大ユーザー数 |
|---|---|---|
| 80K(Cline 型) | 2.80 GB | ~341 |
| 32K(一般的なチャット) | 1.12 GB | ~853 |
これは理論上の上限値であり、運用上の上限ではありません。もし残りの VRAM がすべて KV キャッシュに充てられると仮定すれば上記の数字が成立しますが、現実はもっと複雑です。実際には一度に 341 ユーザーを捌くことはできず、せいぜい 32 ユーザー程度しかサポートできません。その理由については、次のバッチ処理(Batching)のセクションで解説します。
バッチ処理(Batching)
バッチ処理の本質的な目的は、デコード処理がメモリー帯域幅にボトルネックを抱えている点にあります。バッチサイズを 1 にすると、単一のユーザーに対してトークンを 1 つ生成するだけで、HBM から重みデータをすべて読み出すという全コストを支払うことになります。これは明らかに非効率です。すでにデータバス上に存在する重みを、より多くのトークンに流用しない手はありません。
つまり、多数のユーザーによる次のトークンの計算を1つの順次パスにまとめて処理します。各パスではモデルの重みを一度だけ読み込み、バッチ内のすべてのユーザーがその読み込み結果を共有します。もし B 人のユーザーを
必ずJSON形式で返してください。translation フィールドのみ。他のフィールドは一切追加しないこと — 余計なフィールドを書こうとして本文がトークン上限で打ち切られる事故を防ぐため:
{"translation": "リライト全文"}
原文を表示
Preface
imageIf you believe that cheap open weight models are the future then this blog is for you, we all know the why, but I will show you the how grounded in the economics behind it.
I wrote this because I can’t find this information in this form anywhere else. This is a single and arguably the only post that covers both the math of LLM inference and the dollars, grounded in production traffic and real numbers from inference provider negotiations.
If you find any errors in the math of this book, I will personally send you a printed copy of the book version and add you in credits section at the end.
Who is this for?
Software engineers/Managers: shipping open-weight models
AI research/Inference engineers: who want a working model of inference math + pricing
Management Execs and PMs: wondering if self-hosting is worth it. You can skim the math, and read the dollar numbers at the end to decide.
Students: chasing a job at a frontier lab
Prerequisites
All you need is high school algebra: every formula in this post is just multiplication, division, exponents etc. You don't need much ML background; transformers, MoE, KV cache, quantization, and everything else is either explained inline or linked to the best primer I could find. The blog is really dense, though, and the depth + understanding lives in the links. At a minimum budget a weekend if you want to actually internalize it.
What will we work with?
Our running example is Kimi K2.6, with Cline's real production traffic as the ground truth. The math works whether you rent your own GPUs or buy from an inference provider. We'll go in order: load the model, serve inference, batch it, and tune it for production.
Model Architecture
To self-host a model, you first load its weights onto a GPU. How much memory that takes is set by the model's architecture. Kimi K2.6 employs DeepSeek V3-inspired architecture with MoE parameters:
Total parameters: 1 trillion (sparse MoE)
Active Params: 32 billion
Hidden size: 7,168
Attention heads: 64
Routed experts: 384
Shared experts: 1
Experts per token: 8
MoE intermediate size: 2,048
MoE layer frequency: 1
Context window: 256K tokens
Want to derive these numbers from scratch? Read Kipply's legendary parameter counting post.
If you want some background on transformers architecture you must read: The Illustrated Transformer and if you are too tired to read another blog try LLM Visualizer which is the greatest LLM visualization I have ever seen.
Picking the GPU
We'll use the NVIDIA B200 (Blackwell). It's NVIDIA's flagship inference GPU and you can rent one from most neoclouds.
Here’s what you need to know about it:
192 GB HBM3e VRAM per GPU
The standard HGX rack ships with 8 GPUs, wired together by NVLink. NVLink is a fast interconnect between GPUs, so the 8 GPUs can act like one big GPU during inference.
Total GPU memory is 192 GB * 8 = 1,536 GB (~1.5 TB) per 8-GPU node
What does this node actually cost?
Let's lock in one number for the rest of the blog: $6 per GPU per hour. Real B200 pricing in 2026 is closer to $4 if you just rent the GPUS alone, but rounding up gives us a conservative ceiling, if the math works at $6, it will work in real life.
$6/GPU/hour × 8 GPUs = $48 / node / hour
$48 × 24 hours = $1,152 / node / day
$48 × 730 hours (avg month) = $35,040 / node / month
$48 × 8,760 hours = $420,480 / node / year
That $48/hour is your fixed cost. Serving 1 user or 1,000, the meter runs the same. The rest of this blog is about squeezing as many tokens as possible out of that $48/hour as that's what sets your real $/token.
Note:
Self-hosting only makes sense if you're already spending $35K+/month on API inference for this model. The model can't load on a smaller config, so $35K/month is the bare minimum entry ticket.
You can rent just GPUs alone for as low as 3.5-4$ but if you work with inference providers they will charge you 5.5-6$ because they handle the hosting of the model/speculative decoding and all the other model serving magic. As you will later learn in this blog post paying for the extra money to get the models hosted by someone else is a VERY solid deal and much cheaper than hiring an inference engineer if you do it right.
How many GPUs do we need to load the model?
Figure out how big the weights are
Kimi K2.6 has 1 trillion params. We'll run it in FP4 quantization (0.5 bytes per param). Quantization basically means storing each weight in the model with fewer bits, like rounding $4.7283910 up to $5. The model gets way smaller in memory, and if done carefully, it gives almost the same answers.
FP4 is the aggressive quantization tier, and modern models are trained quantization aware, so the quality hit is not that bad, the models are easier to host, and far less memory is needed to load them on GPU.
weight_bytes = 1,000,000,000,000 × 0.5 byte = 500 GB
Divide by your GPU memory
500 GB ÷ 192 GB per B200 = 2.60
So 3 B200s technically fit the weights of FP4 quantized model. That's the floor and its enough to load the model into VRAM and nothing more.
Quantization and Quality
Quantization is a trade off between price and quality. On the pricing side, every number downstream of this section is linear in bytes-per-param. FP4 puts the weights at 500 GB; FP8 doubles that to 1 TB (you'd need 6 B200s, not 3); BF16 doubles it again. FP4 is the cheapest tier that still ships acceptable quality on modern quantization-aware models, which is why we use it. If your evals say FP4 hurts your workload, redo the chain at FP8 as the math still works, it just costs more. Note: FP4 here means NVFP4 specifically, Blackwell's native 4-bit format. And we'll use "FP4" throughout the blog for brevity.
On the quality side, the trade-off isn't visible on a spec sheet. Some providers offer dirt-cheap, low-latency inference but quantize so aggressively that output collapses no matter how good their latency SLAs(Service Level agreements) look. The only way to know what you're shipping is to run evals (our setup is here).
How many GPUs do we need to serve the model?
Loading the model is one thing. Serving real traffic is another, and it costs more VRAM. Every concurrent user needs their own slice of KV cache (per-user memory that keeps attention from being quadratic so that new inference requests use caching). You also need bandwidth and headroom to batch their requests efficiently. We'll cover KV Cache, bandwidth and headroom in the next sections, for now, just trust that this is where the rest of the VRAM goes.
So we're taking the full 8-GPU B200 node: 1,536 GB of total VRAM. Here's how that breaks down:
What
Math
Memory used
Remaining
Total VRAM on the node
192 GB × 8 GPUs
—
1,536 GB
Model weights
1T params × 0.5 byte
500 GB
1,036 GB
Activations (working memory during a forward pass)
~80 GB
956 GB
Free for KV cache (i.e. concurrent users)
~956 GB
That ~956 GB is the budget for actually serving users. The next several sections are how we spend it.
imageServing the model
Two things happen on every request: the model reads the whole prompt (prefill), then writes tokens one by one (decode). We'll cover decode first because it's the dominant cost on long generations, then circle back to prefill.
Here's the TLDR of Decode. LLMs generate one token at a time. The model writes a token, looks at everything so far (your prompt + the tokens it just wrote), and writes the next one. It loops until its done.
[prompt] → token_1
[prompt + token_1] → token_2
[prompt + token_1 + token_2] → token_3
...
Each loop iteration is one forward pass: the input runs through dozens of layers, each layer reads its slice of weights from VRAM and hands its output to the next, and at the end you get a probability distribution over the next token. The model samples one and repeats.
So inference is just: read weights from VRAM → matrix math → emit a token → repeat.
Emitting a token (Decode)
For the 32B active params, if we have to generate an output token we need the following data flow(FP4 quantization is 0.5 bytes per param):
bytes_read_per_token = 32B active × 0.5 byte = 16 GB
16 GB of weight data flowing across the bandwidth pipe for every single token we generate. This is the main bottleneck number.
The B200 does 8 TB/s of memory bandwidth per GPU. Sounds enormous, but watch what happens when we run the math. Max output speed is just bandwidth ÷ bytes_per_token.
Single B200: 8 TB/s
8-GPU node (raw): 64 TB/s
8-GPU node (real): ~50 TB/s after sync overhead
50,000 GB/s ÷ 16 GB/token ≈ 3,125 tok/s theoretical
At 10–12% real-world MBU* ≈ 312–375 tok/s aggregate decode
So at small batch sizes, a full 8-GPU B200 node serving Kimi K2.6 in FP4 hits a theoretical ceiling of roughly 3,125 tokens per second of aggregate decode.
Decode is sequential so you can't generate token N+1 until token N is done. That's why decode is bandwidth-bound, and why TPS (tokens per second) is the metric that decides how fast the output streams. (Exception: speculative decoding.)
Caveats of theoretical max decode throughput vs actual max throughput
The 16 GB/token figure above assumes that every token reads its own personal slice of experts, which is true at batch=1, but it stops being true the moment you batch. Once many users flow through the same forward pass, tokens share expert reads inside MoE, the effective bytes-per-token shrinks, and aggregate decode climbs well past this number. There are also other aspects to consider. We'll work out exactly how this works in the Batching section.
That 3,125 tok/s number is theoretical: what you actually get is determined by your MBU (Memory Bandwidth Utilization), the fraction of nominal bandwidth your inference stack actually delivers to useful work. MBU varies widely: We measured ~11% MBU on vLLM + Kimi K2.6 + 8× B200 + 80K context, on the lower end.
Our practical takeaway is that you shouldn’t trust theoretical ceilings, and don't trust vendor claims either. You can do load tests and compute your achieved MBU as
(measured aggregate decode tok/s × bytes_per_token) ÷ nominal_node_bandwidth
Then cross-reference it with research papers to see if you are too far off, and if you are too far off then you must find out why.
Before going further, there's two ideas you need to lock in that will explain the real bottlenecks of GPU performance for inference and they are:
Memory-bound vs compute-bound
Arithmetic intensity
Memory Vs Compute bounds
This shows up constantly in transformer inference, and in deep learning optimization more broadly. The basic idea is that: to do any math on a GPU, you first have to pull the weights out of memory, which costs memory bandwidth. The good news (and this has been very well optimized) is that the GPU can start computing as soon as the first weights arrive memory reads and math run in parallel.
So at any given moment, one of two things is happening:
Compute-bound/Flop-bound: In this case, the GPU is choking on math. The math units are fully busy, and memory is sitting idle. A FLOP is one floating-point operation. One multiply, one add, one of those. When people say a GPU does "15 PFLOPS," they mean it can do 15 × 10¹⁵ floating-point operations per second. You can read more about compute/flop bounds in these lecture notes.
Memory-bound: the memory pipe is fully busy, and the math units are sitting idle.
Let me remind you once again that decode is memory-bandwidth-bound, and that is a huge bottleneck on how fast we can do our inference.
Arithmetic intensity
Since at any point the GPU is either memory or compute bound. Arithmetic intensity is the knob that flips a workload between the two: FLOPs done per byte read from memory.
arithmetic_intensity = FLOPs performed / bytes read from HBM
Every GPU has a break-even point (the "ridge" of the roofline model) where compute and bandwidth finish at the same time. Below the ridge you're memory-bound; above it you're compute-bound.
For the B200 at FP4:
ridge = peak_flops / peak_bandwidth
= 10 PFLOPS / 8 TB/s
≈ 1,250 FLOPs per byte
So on a B200, a kernel needs to do ~1,250 ops per byte of weight before compute becomes the bottleneck. Anything less and the math units are sitting idle waiting on HBM.
Now look at where decode and prefill land:
Decode (batch=1): ~2 FLOPs per byte read (one multiply-add per weight value). Deep in memory-bound territory. ~600× below the ridge. This is why decode tok/s is dictated by bandwidth, not flops(as i had mentioned before).
Prefill: You read the same weight once and reuse it across thousands of tokens (or batching). Arithmetic intensity scales roughly linearly with how many tokens share that read. Push enough tokens through one forward pass and you cross the ridge into compute-bound land.
This is the lens to keep in your head for the rest of the blog. Every optimization that follows is, underneath, a trick to raise arithmetic intensity so each byte of HBM traffic produces more useful tokens. As we do load testing later and put more weight on our GPUs, we'll see both of these bounds in practice.
Loading the prompt tokens (Prefill)
The next concept you need to learn is prefill. Prefill is when the whole prompt the user throws at you gets read in a large parallel mat mul operation so that the model can "process it" and give you a response (decode).
imagePhoto from the illustrated transformerWhy can you do prefill in parallel?
Because you already know the entire sequence, you can push it through the layers in parallel. In one weight read, thousands of tokens get processed simultaneously. The bandwidth bottleneck disappears because you're amortizing one read across thousands of tokens.
Prefill is compute-bound. In our case, the B200 GPU has way more compute than bandwidth: ~10 PFLOPS dense at FP4 per GPU, and we have 8 GPUs.
Realistic prefill speeds reach ~78,000 input tokens/sec aggregate on an 8-GPU B200 node, roughly 1 coding-agent-sized fresh prompt processed per second on a long Kimi K2.6 conversation. That's what we'd expect to measure at Cline running this workload.
Math to explain it
Flops per GPU = 10 PFLOPS
flops_per_token = 2 × 32B active = 64 GFLOPs
node_compute = 8 GPUs × 10 PFLOPS = 80 PFLOPS (dense FP4)
theoretical_max = 80 PFLOPS ÷ 64 GFLOPs ≈ 1.25M tok/s
realistic ≈ 6.4% MFU (attention quadratic + MoE all-to-all,
partially offset by B200 attention pipeline)
≈ 78,000 tok/s on long prompts (this was what we got in load testing)
MFU(Model FLOPS Utilization) = (achieved FLOPs/sec on model work) / (peak FLOPs/sec of the hardware)
MFU is the reality check on your prefill numbers. Compare your measured MFU against the ranges published in literature if you're too far off, either your stack has a real problem or another provider is squeezing far more out of the same hardware.
TTFT: Time To First Token
This is where the metric TTFT (Time To First Token) comes from, the wait between hitting enter on chat and seeing the first character stream back. Everything before the first token appearing on chat is prefill burning compute. Everything after is decode burning memory bandwidth.
If your node prefills at 80,000 tok/s and a user shows up with an 80,000-token prompt:
80,000 tokens ÷ 80,000 tokens/sec = 1 second TTFT
In practice, two things change this number by a lot in different directions:
- Batching: That 80K tok/s is the whole node of the entire GPU. If 16 users are prefilling concurrently, each one only gets ~5,000 tok/s of effective throughput. An 80K prompt now takes ~16 seconds. Per-stream and aggregate are very different numbers, and you need load tests in different configurations to figure this out. We will explain batching more later in this document.
- KV cache/Prompt reuse: In coding agents and chat, conversations build on top of each other. When a user fires off their 5th message in a long thread, you're not re-prefilling the entire 80K context the KV cache from earlier turns is already sitting in VRAM. You only prefill the delta: the new user message plus whatever fresh context got pulled in (file reads, tool outputs, etc).
At Cline, our system prompt is small, roughly 3–4K tokens, and most of the tokens come from file reads/searches over the back-and-forth conversation. Even when total context is 80K, the actual new tokens being prefilled on a given turn are usually 8–10K, mostly from file reads.
KV Cache: where the 956 GB actually goes
Remember that ~956 GB of free VRAM we left in the bank earlier? This is where we spend it.
Here's the core problem KV cache solves. Every time the model decodes a new token, the attention layer needs the K (key) and V (value) vectors of every previous token in the context. Without caching, you'd recompute every K and V from scratch on every single decode step, turning each new token into a fresh prefill of the entire history. That's quadratic work for nothing.
The fix is simple: K and V from past tokens are deterministic functions of those tokens, and the model weights don't change. So the K and V you compute at step 5 are literally the same numbers you'd compute again at step 6, step 7, step 10. Compute once, keep in VRAM, read back on every future step.
imageThe picture above is the main intuition.
Insight 2: the next token's attention only needs the new token's query vector and all past key/value vectors. New Q every step, but the Ks and Vs from prior steps are reusable forever.
imageSo the cache works like this: on token 5, you generate K_5 and V_5 fresh and append them to the K/V buffers. Tokens 1–4 get pulled from cache. On token 6, you append K_6 and V_6 and pull tokens 1–5 from cache. One new pair per step, never recomputed. That's the whole game.
How big is the cache, in bytes?
DeepSeek V3 and Kimi, which inherits the attention architecture, use MLA: Multi-head Latent Attention. Instead of caching K and V for every head, MLA compresses them into a single shared latent vector per layer plus a small RoPE component. The cache size becomes independent of head count.
bytes_per_token (MLA) = num_layers × (kv_lora_rank + qk_rope_head_dim) × bytes_per_value
= 61 × (512 + 64) × 1
≈ 35 KB / token / user
Caching in the 956 GB
KV per user = 35 KB × context_length. Free VRAM = 956 GB. So:
max_users ≈ 956 GB / (context_length × 35 KB)
Context length
KV per user
Theoretical max users
80K (Cline-shaped)
2.80 GB
~341
32K (typical chat)
1.12 GB
~853
This is the theoretical ceiling, but not the operational ceiling. All of this would only be true if we assume that the entire remaining VRAM was just used for KV cache but the truth is far more complex. We can't actually support 341 users at the same time(we can barely support 32). Now let’s figure the why out in the batching section up next.
Batching
The whole point of batching is that decode is memory-bandwidth-bound. At batch size=1, you pay the full cost of pulling weights from HBM just to generate a single token for a single user. That's wasteful, the weights are already on the wire, you may as well pipe more tokens.
So you stack many users' next-token computations into the same forward pass. Each pass reads the model weights once, and every user in the batch shares that read. If you can fit B users into a
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み