スケール時の推論コストをナプキン計算で算出する方法(13 分読)
本記事は、AI モデルの推論コストを GPU のスペックやアーキテクチャに基づき紙上で簡易計算する手法(ナプキン・マス)を解説し、SaaS プロダクトの収益性とスケーラビリティを評価するための実用的なフレームワークを提供している。
キーポイント
推論コスト計算の基礎要素
GPU のピークスループット(TFLOPs)とメモリ帯域幅、コンテキスト長、モデルのパラメータ数、およびプロダクトのユーザー行動特性という 4 つの主要変数に基づき、コストを算出する必要がある。
アーキテクチャ依存性の低さ
拡散モデルなどの特殊なケースを除き、LLM の具体的なアーキテクチャの詳細は、推論コストの概算計算においてはそれほど重要ではなく、基本リソース計算で十分である。
KV キャッシュによる最適化
推論エンジンの最適化技術として KV キャッシュ(Key-Value Cache)を活用することで、コンテキスト長が増加しても計算量を大幅に削減し、単一 GPU での同時ユーザー数を数百人にまで引き上げることが可能になる。
スケーラビリティと収益性の関係
1 つの GPU で処理できるトークン数やユーザー数を算出することで、サブスクリプション型プロダクトにおける価格設定と利益率を現実的に予測し、ビジネスモデルの健全性を検証できる。
推論コスト計算の核心指標
GPU の性能評価には「ピークスループット(FLOPs)」と「メモリ帯域幅」の2つの主要な数値が必要であり、モデルアーキテクチャの詳細はこれらに比べて重要度が低い。
単純化された計算前提条件
紙上でコストを算出するためには、コンテキスト長(20万トークン)、パラメータ数(32B)、およびユーザーの duty cycle などの製品特性という4つの基本情報を把握すれば十分である。
FP-8量子化を前提とした計算
スループットの計算には FP-8 量子化を仮定しているが、この手法は FP-16 など他の形式への調整も容易であり、コスト見積もりの基礎となる。
影響分析・編集コメントを表示
影響分析
この記事は、AI エンジニアリングやプロダクトマネージャーにとって、膨大な計算リソースを要する複雑な推論プロセスを、直感的で実用的な数値モデルに変換する方法を示しており、AI プロダクトのビジネスモデル構築における意思決定支援に大きく寄与します。特に、ハードウェア進化に伴うコスト変動を予測し、収益性を確保するための具体的な計算ロジックを提供することで、業界全体の効率化と持続可能な開発を促進する重要な指針となります。
編集コメント
技術的な詳細を深く掘り下げつつも、最終的にはビジネス視点(コストと収益)に落とし込む構成が非常に秀逸です。AI プロダクト開発者や経営層にとって、技術的負債やスケーリングの壁を数値で可視化するための強力なツールとなるでしょう。
Jun 14
もし AI モデルをプロダクトのスタックの一部として提供しているなら(2026 年において避けるのは難しいでしょう)、
A100/H100/H200/B200/あるいはその他どのようなハードウェアでも、単一の GPU からどれだけの電力(処理能力)を引き出せるかという計算は既に行っているはずです。
これはサブスクリプション型プロダクトの価格設定に直接影響します。
モデル、ハードウェア、推論エンジンが進化しても、ユーザーあたりのドルコストは紙の上で簡単に算出できることを示したいのです。
この演習を通じて、推論エンジンにおけるさまざまな最適化が、SaaS プロダクトの収益性をどのように支えているかも明らかになるでしょう。
もし実際に紙上でこれを計算する必要があるなら、以下の情報だけで十分です:
- GPU ハードウェア仕様:メモリ帯域幅とピークスループット(以下で説明)。
- コンテキスト長:200k トークンを想定。
- モデルのアクティブパラメータ数:単一 GPU での計算をシンプルにするため、32B を想定。
- プロダクトに関する概略情報:ユーザープロンプトに依存しているか、プログラムされたループで駆動されているか、ユーザープロファイルの稼働率(末尾で説明)など。
モデルアーキテクチャの詳細は、拡散モデルのような全く異なるものでない限り、意外にもそれほど重要ではありません。
LLM のアーキテクチャに慣れている場合は、以下の凡例を使って興味のあるセクションへスキップしてください:
- 単一 GPU 上のリソース
- 行列乗算のコスト
- 言語モデルの概要
- アテンションの詳細な解説
- KV キャッシュによる計算量の削減
- トークン 1 つあたりのコストは?
- 現実的に何人のユーザーをサービスできるか?
- GPU 上で数百人のユーザー向けに最適化する方法
- トークン/秒数
- ユーザー 1 人あたりのドルコスト
単一 GPU 上のリソース
市場にあるあらゆる GPU について、その仕様書には 2 つの主要な指標が記載されています。
- ピークスループット:1 秒間に実行される浮動小数点演算の数。通常はテラ FLOPs(TFLOP/s)で表されます(1 TFLOP/s = 10^12 ops/sec)。
- メモリ帯域幅:グローバルメモリ(VRAM)からレジスタ(SRAM)へ移動できるデータの量。通常は TB/sec で表されます。
計算には FP-8 量子化を仮定しますが、FP-16 の場合でも同様に数式を調整することは容易です。
行列乗算のコスト
この記事をクリックしたのであれば、AI モデルが*巨大な*行列に対して*多数の*行列乗算を実行していることはご存知でしょう。したがって、まず行列乗算(matmul)のコストを求めることから始めるのは驚くべきことではありません。
2 つの行列を仮定します:A と B。
その積を行列 C とします。
高校の代数から、C の各要素は以下のように計算できることがわかります:
ここで、行列乗算における「コスト」に関する最初の洞察が得られます。各 C^{i,j} について、初期値を 0 から始め、以下の手順を実行する必要があります。
- メモリから A^{i,k} を読み込む。
- メモリから B^{k,j} を読み込む。
- これらを掛け合わせる。
- #3 の結果をこれまでの累積和に加算する。
これは各アイテムあたり合計でこの回数行われます。
したがって、(N,d)*(d,M) 行列積のコストは、メモリアクセスが○回、浮動小数点演算が○回となります。
タイル化(tiling)と呼ばれる最適化を行うと、メモリアクセス数は約○回に削減されます。
詳細は必須ではありませんが、興味のある方のために Alvin のブログ記事 に記載されています。
ランゲージモデルの概要
LLM(大規模言語モデル)の本質は単純です。N 個の単語のシーケンスを受け取り、N+1 番目の単語を生成します。
各単語は d 個のエントリを持つベクトルとして表現されます。
後ほど説明する「アテンション(attention)」と呼ばれる関数を繰り返し適用することで、次の単語を予測します。
単一のフォワードパスはおおむね以下のようになります:
y = input() # y は N x d サイズの行列
for each layer in the network:
y = attention(y)
最終層の出力を単語確率に変換する。
W_vocab = d x vocab_len サイズの行列、
vocab_len はモデルの語彙に含まれるすべての単語の数。
token_probs = softmax(y * W_vocab)
next_tok = token_probs(argmax(token_probs))
next_tok は (1 x d) サイズのベクトル
これが LLM が自己回帰的(auto-regressive)と呼ばれる理由でもあります。彼らは <stop> トークンが生成されるまで、自身の出力に対して複数のフォワードパスを継続して実行できます。
これは、RoPE を省略している箇所や、その間の MLP レイヤー、末尾のトークンサンプリングなど、多くの部分を簡略化した概要です。
前述した通り、これらを追加しても、フェルミ推定によって計算が成立することを検証できます。
詳細なアテンション機能
アテンション関数を拡大鏡で見てみましょう。
ご覧の通り、入力は行列であり、は単一の次元ベクトルです。
ネットワーク内の各「レイヤー」において、モデルは行列を保持し、以下のように「アテンション」を計算します:
, and
あるいは、Python では以下のようになります:
def attention(X, W_q, W_k, W_v):
Q,K,V = X @ W_q, X @ W_k, X @ W_v
Q_KT = Q @ K.transpose(2,1)
return softmax(Q_KT / sqrt(d_model)) @ V
ここで@は、2 つの行列の内積(ドット・プロダクト)を意味します。
実際には、複数の LLM 会話(大規模言語モデルの対話)が並列処理されます。つまり、推論はバッチ処理され、チャットを同時に処理することになります。これにより、入力シーケンスとなります。
紙の上で計算を実行して、追跡できるか確認してください。
Python コードでは、転置(トランスポーズ)の引数だけが変更されます:
- Q_KT = Q @ K.transpose(2, 1)
+ Q_KT = Q @ K.transpose(0, 2, 1)
ただし、アテンションの実装には一つの課題があります。それはメモリから読み込むデータが多すぎることです。単一の行列積(マトリックス・マルチプライケーション)、すなわち を見てみましょう。
モデルを提供する企業では、ユーザーが最大約 20 万トークン程度までチャットできるようにしています。
単一の K@W_k の行列積の場合、以下のようになります:
X = tensor(B, N, d) # "B" chats, each with a maximum of "N" 'tokens'.
W_k = tensor(d, d) # weights have no batch dimension
O = tensor(B, N, d) # result of X @ W_k
Notice that the output is another tensor.
As established in the matmul cost section, to compute each , we need memory reads and compute operations.
For a batch size of (number of concurrent conversations), we get:
- Floating-point operations: .
- Memory accesses: .
Assume N to be roughly 200k, and d to be 8192 (most common outside frontier labs).
Meaning that to generate one token for a single user, we need 26 trillion floating-point ops and 1.7 billion memory accesses. This is *with* the tiled matmuls. That's way more compute ops than memory reads. In fact, we're doing four orders of magnitude more compute than memory accesses. The next batch of input will have to wait tens of thousands of cycles for the GPU to finish with the current batch.
On diagramming the above matmuls out on paper, you'll notice a key detail— we're wasting far too many resources to re-compute the matmul products for tokens that were already processed in a previous iteration.
Recall that LLMs are auto-regressive. They:
- Take a list of tokens , do a bunch of matmuls.
- Repeatedly do attention(X, weights) at L (for L layers), and generate a new token
- append to (the chat thus far).
- Put the output of 3 back into step 1, until a "STOP" token is generated.
すべての新しい単語に対してチャット履歴全体を再度処理することを避けるために、推論エンジンはペアをキャッシュして再利用します。
KV-Cache を用いた計算量の削減
各チャットの中間出力、すなわち と は、すべてのレイヤーでキャッシュされ、VRAM のある領域であるKV Cacheに保存されます。vLLM などの推論エンジンでは、プログラマーがこのために事前に割り当てる VRAM の割合を決定できます。
もちろん、私が説明したほど単純ではありません。vLLM に与えられたメモリを最適に活用するために多くの工夫がなされており、その詳細は元の著者による このプレゼンテーション でご覧いただけます。
私たちの簡易計算(napkin math)においては、KV キャッシュの存在により一つの簡略化が可能になります:順伝播(フォワードパス)ごとに、履歴全体ではなく最も直近に生成された単語のみを処理すればよいのです。つまり、 を処理する代わりに、 (最新のトークン)を処理することになります。
X @ W_k の計算式は以下のようになります:
X = tensor(B, 1, d)
W_k = tensor(d, d)
O = tensor(B, 1, d)
バッチサイズ(同時進行する会話の数)を とすると、以下が得られます:
- メモリアクセス数:約 2620 万回
- 演算回数:約 5240 万回
つまり、メモリアクセス 1 回あたり、1 万回ではなく*2 回の*演算のみを行えばよいことになります。バッチ全体では、メモリアクセス 1 回あたり 2*B 回の演算を行っています。これは素晴らしい結果です!さて、ここで利用可能な最速 GPU の仕様書を取り出して、1 秒間に生成できるトークン数(および対応可能なユーザー数)を計算してみましょう。
トークン1 つの費用はいくら?
残りの議論では、NVIDIA B200 を主な例として取り上げましょう。ウェブ検索によると、この GPU には以下の仕様があります:
- メモリ帯域幅:8 TB/s(つまり、1 秒間にアクセスできるバイト数)。
- 計算集約度:4500 TFLOP/s(つまり、1 秒間に処理できるバイト数)。
お分かりでしょうか?
Blackwell クラスの GPU は、データをロードする速度よりも562 倍も速くデータを処理できます。
言い換えれば、このようなチップから最大限の性能を引き出すには、ロードされるバイト 1 つあたり562 回の計算を行う必要があります。
これより多いとメモリ帯域幅が遊んでしまいます(例えば KV キャッシュがない場合など)。
これより少ないと計算コアが遊んでしまいます。
私たちは現在、2*Bの計算を行っています。では、B200 の計算能力と帯域幅の予算を完全に使い切るために、同時に何人のユーザーにサービスを提供すべきでしょうか?
単一の NVIDIA B200 GPU を使用する場合、投資効果を最大化するには331 人のユーザーを同時処理する必要があります。
もちろん、これは理論上の上限値です。実際には VRAM(ビデオメモリ)が限られています。モデルの重みと巨大な KV キャッシュをそこに詰め込む必要があります。
現実的に何人のユーザーにサービスを提供できるか?
32B の密結合モデルを想定しましょう。これは、192G のチップが快適にサポートできる程度の規模です。
これは Gemma、Qwen、DeepSeek など、どのようなモデルでも構いません。
異なる技術やパラメータサイズは互いに相殺し合い、おおよそ同じ結果をもたらします(誤差は 5〜10% 程度)。
さて、問題に戻りましょう。32B のモデルがあります。
これは VRAM 上で 32*10^9 バイト、つまり 32GB を占めます。
コンテキストウィンドウを =200k トークンと仮定しましょう。
各層における入力は –次元です。
各レイヤーごとに、K と V の行列ペアに対して 1 バイトを保存する必要があります。
私たちの規模のモデルでは通常、d=8192、L=64 となります。これにより以下が得られます:
KV キャッシュサイズ = 2 * N * L * d
= 2 * 200_000 * 64 * 8196
= 210 GB (!!)
これは、GPU が持つ VRAM よりも多くなります!
ここでは、このような規模のモデルが採用するもう一つの最適化手法を引用します:Grouped-Query-Attention。アテンション(注意機構)が初めての場合は、これは今後の読書のために保存しておき、KV キャッシュサイズを約 8 倍削減するという私の主張に信頼してください。
ただし、Multi-Head-Attention(多头注意力机制)に慣れている場合、GQA は単純です:複数のクエリヘッド間で同じ KV ヘッドを共有します。つまり、64 のクエリヘッドに対して、合計でわずか 8 つの KV ヘッドを使用します。具体的には、Q-heads 0-7 が最初の KV-head を共有し、Q-heads 8-15 が次の KV-head を共有し、というように続きます。
GQA を使用すると、KV キャッシュは現在、チャットシーケンス(またはユーザー)あたり約26GBになります。
重みにはすでに32GBを使用しているので、残りの 160GB の KV キャッシュに同時に保存できるチャットコンテキストは何個でしょうか?
それは 160/26 = 6 です。
つまり、約 6 つのチャットが並列で実行されます。これは…低いように思えます。
GPU 上で数百人のユーザーに対応するための最適化。
多くのコンテキストは、顧客に提示するコンテキストウィンドウが 200k トークンであっても、その限界に達することはありません。
製品によっては、LLM 会話の中央値は 4,000〜40,000 トークンの anywhere に分布します。
KV キャッシュをチャンクに分割し、トークンの使用量が増えるにつれてこれらのチャンクを異なるユーザーに割り当てることができます。
放棄された/コールド状態の会話スレッドはキャッシュからフラッシュされます。
これは vLLM が PagedAttention で行っていることです。
ユーザー活動の中央値に応じて、会話長の仮定次第でBlackwell チップあたり 40〜60 ユーザーをサービス提供できます。
あなたのプロダクトの性質も重要であることを覚えておいてください。
ほとんどの ChatGPT スタイルのアプリでは、ユーザーはプロンプトを入力するよりも読むことに時間を費やします。
中央値のチャットセッションにおいて、ユーザーはおそらく 80% のアイドル状態になります。
ここで GPU の稼働率は 20% (!) です。
したがって、現実的には、アプリの種類に応じて 1 チップあたり約 300〜800 ユーザーを快適にサービス提供できます。
もちろん、ループでエージェントにデータを供給するハーンネスを使用している場合はこの限りではありません。
Tokens Per Second
以前、100% の稼働率で 6 ユーザーを快適にサポートできることを見ました。
しかし、彼らにとって観測される速度はどうなるでしょうか?
これもまた、メモリと計算の比率の結果です。
単一のフォワードパスでは、モデルの重みと KV キャッシュ全体を VRAM からレジスタへ*一度だけ*転送します。
その後、読み込まれたバイトごとに 2*B の演算を行います。
したがって、消費される総時間は以下のようになります:
データ移動に要する時間(秒)
= メモリ容量 (GB) / バンド幅 (GBps)
= 190GB / (8*10**3) GBps
= 0.02375 秒
= 23.75 ms
計算に要する時間
= 190 * 2 * 6 / 4500 TFLOPs
= 0.5ms
両方の処理が並列で行われるため、
演算コアは時間の 98% をアイドル状態(待機中)にします。
24 ミリ秒ごとに B=6 トークンを生成します。
1 秒 (=1000 ミリ秒) あたり、6 人のユーザーに対して約 250 トークン、
つまりユーザーあたり 1 秒で約 40 トークンを生成することになります。
LLM の出力が読まれることを想定している場合(背景で SQL クエリを構築する場合とは異なります)、
1 秒あたり 40 トークンは、ほとんどの人の読書速度を超えています。
ユーザーあたりのドルコスト
これは主に、ハードウェアを所有しているかレンタルしているかに依存します。
B200 が 1 台 $40,000 の場合、ユーザーあたりの生涯コストは 40_000/num_users となります。
100% デューティサイクルの場合(コスト面で最悪のケース)、これはユーザーあたり 6,000 ドルになります。
現実的には、GPU あたり 500 人のユーザーをサービスする場合、
ユーザーあたりの生涯コストは約 $133 となり、さらにデータセンターや維持管理費が追加されます。
もし GPU をレンタルする場合は、コスト計算はより単純です。
B200 のレンタル料が時間あたり $3 の場合、ユーザーあたりの時間当たりコストは 3/num_users です。
num_users=500 の場合、ユーザーあたり時間当たり約 $0.006、
つまり月額で $4.32 となります。
したがって、ユーザーから $4.32 より多く請求していれば、運営コストはカバーされます。
AI 企業として、複数の GPU をお持ちになるでしょう(そう願っています)。
そのため、GPU クラスター全体でユーザーの負荷分散を行うことになりますが、
その場合、私たちの方程式は少し変化します。
残念ながら、ナプキンの計算スペースはもうありません。
原文を表示
Jun 14
If you serve AI models as a part of your product's stack (hard not to in 2026),
you've done the math on how much juice you can get out of a single
A100/H100/H200/B200/whatever.
This directly affects the pricing for subscription-based products.
I want to show that even as models, hardware, and inference engines evolve;
the dollar price-per-user remains straightforward to work out on paper.
This exercise should also reveal how various optimizations in inference engines
help SaaS products remain profitable.
If you were actually working this out on paper, you'd need only the following information:
- GPU hardware specs: Memory bandwidth and peak throughput (explained below).
- Context length: assumed 200k tokens.
- Active parameter count of the model: Assumed 32B to keep things simple on a single GPU.
- Some idea about your product: Whether it's driven by user prompts or programmed loops, duty cycle of your user profile (explained at the end), etc.
The specifics of the model architecture matter surprisingly little,
unless it's something entirely different like diffusion.
If you're comfortable/familiar with the architecture of LLMs, use this legend to skip to the sections that interest you:
- Resources on a single GPU
- Cost of a Matrix Multiplication
- An Overview of Language Models
- Attention in Greater Detail
- Reducing Compute with KV-Cache
- How much does a token cost?
- How many users can you serve realistically?
- Optimizing for hundreds of users on a GPU
- Tokens Per Second
- Dollar cost per user
Resources on a single GPU
For any GPU on the market, you can find on its spec sheet
two key metrics:
- Peak throughput: Number of floating-point operations executed per second. Usually in TeraFLOPs
(1 TFLOP/s = ops/sec).
- Memory bandwidth: Amount of data that can be moved from global memory (VRAM) to registers (SRAM). Usually in TB/sec.
We'll assume FP-8 quantization to compute throughput, though it's easy to adjust the math for FP-16 as well.
Cost of a Matrix Multiplication
If you bothered to click on this article, you know that AI models do *many* matrix multiplications on *massive* matrices. That we start by finding the cost of a matmul should be no surprise then.
Assume two matrices: and .
Let their product be the matrix .
From high school algebra, we know that each element of can be computed as:
In this, we find our first insight into the "cost" of a matrix multiplication. For each , we need to start with an initial value of 0 and:
- Load from memory.
- Load (B^{j,k}) from memory.
- Multiply them together.
- Add the result of #3 to the cumulative sum so far.
And this is done a total of times *per item.*
So, the cost of a (N,d)*(d,M) matrix product
is memory accesses and floating-point operations.
With an optimization called tiling,
the memory access goes down to about .
The details aren't necessary to proceed, but Alvin's blog post
has them for those curious.
An Overview of Language Models.
At their core, LLMs are simple –
they receive a sequence of N words and generate the N+1th.
Each word is represented as a vector with d entries.
Using repeated applications of a function called "attention" (explained later), they predict the next word.
A single forward pass roughly looks like this:
`
y = input() # y = matrix of size N x d
for each layer in the network:
y = attention(y)
# Convert the final layer's output to word-probs.
# W_vocab = matrix of size d x vocab_len,
# and vocab_len is the number of all words
# in the model's vocabulary.
token_probs = softmax(y * W_vocab)
next_tok = token_probs(argmax(token_probs))
# next_tok is a (1 x d) vector`
This is also why LLMs are called auto-regressive. They can keep doing multiple forward passes over their own output until a <stop> token is generated.
This is a simplified overview of where I'm skipping RoPE,
the MLP layers in between, token sampling at the end,
and much more.
As mentioned earlier,
you can add those in and still verify that our math will work out
by a Fermi estimation.
Attention in Greater Detail
Let's place the attention function under a magnifying glass.
As you saw, the input is a matrix , and is a single dimensional vector.
For every "layer" in the network, the model stores matrices , and computes "attention" as follows:
, and
Or, in python:
`
def attention(X, W_q, W_k, W_v):
Q,K,V = X @ W_q, X @ W_k, X @ W_v
Q_KT = Q @ K.transpose(2,1)
return softmax(Q_KT / sqrt(d_model)) @ V`
Where @ is the dot-product of two matrices.
In reality, multiple LLM conversations are processed in parallel.
So inference is batched—where we process chats concurrently.
This means our input sequence .
Work the math out on paper to verify it tracks.
In our Python code, just the transpose arguments change:
`
- Q_KT = Q @ K.transpose(2, 1)
+ Q_KT = Q @ K.transpose(0, 2, 1)`
Only, there's one trouble with our implementation of attention: it reads too much data from memory. Let's look at a single matmul, the . Companies that serve models will allow you to chat with them for up to 200k or so tokens.
For a single K@W_k matmul, it looks like this:
`
X = tensor(B, N, d) # "B" chats, each with a maximum of "N" 'tokens'.
W_k = tensor(d, d) # weights have no batch dimension
O = tensor(B, N, d) # result of X @ W_k`
Notice that the output is another tensor.
As established in the matmul cost section, to compute each , we need memory reads and compute operations.
For a batch size of (number of concurrent conversations), we get:
- Floating-point operations: .
- Memory accesses: .
Assume N to be roughly 200k, and d to be 8192 (most common outside frontier labs).
Meaning that to generate one token for a single user, we need 26 trillion floating-point ops and 1.7 billion memory accesses. This is *with* the tiled matmuls. That's way more compute ops than memory reads. In fact, we're doing four orders of magnitude more compute than memory accesses. The next batch of input will have to wait tens of thousands of cycles for the GPU to finish with the current batch.
On diagramming the above matmuls out on paper, you'll notice a key detail— we're wasting far too many resources to re-compute the matmul products for tokens that were already processed in a previous iteration.
Recall that LLMs are auto-regressive. They:
- Take a list of tokens , do a bunch of matmuls.
- Repeatedly do attention(X, weights) at L (for L layers), and generate a new token
- append to (the chat thus far).
- Put the output of 3 back into step 1, until a "STOP" token is generated.
To avoid re-processing the entire chat history *again* for every new word,
inference engines will cache the pairs for reuse.
Reducing Compute with KV-Cache
The intermediate output on every chat, namely and ,
is cached at every layer, and stored in a region of VRAM called the
KV Cache.
Inference engines like vLLM allow programmers to decide what
percentage of VRAM should be pre-allocated for this.
Of course, it's not as easy as I made it sound. There's a lot of cleverness applied to make optimal use of the memory vLLM is handed, the details for which you can find in this presentation by the original authors.
For our napkin math,
the existence of KV-cache allows one simplification:
for every forward pass, we get to process only the most recently generated word, rather than the entire history.
i.e., instead of processing a ,
we get (the most recent token).
The math for X @ W_k now becomes:
`
X = tensor(B, 1, d)
W_k = tensor(d, d)
O = tensor(B, 1, d)`
For a batch size of (number of concurrent conversations), we get:
- ~26.2 million memory accesses
- ~52.4 million ops
Meaning that for every memory access made, we need only perform *two* operations rather than 10 thousand.
For the entire batch, we're doing 2*B operations per memory access.
This is fantastic! Now, let's pull out the spec-sheet for the fastest GPU available and figure out how many tokens we can generate per second (and for how many users).
How much does a token cost?
Let's take the NVIDIA B200 as our leading example for the remainder of this. From a web search, you'll find that it has the following specs:
- Memory bandwidth: 8 TB/s (Or bytes accessed per second).
- Compute intensity: 4500 TFLOP/s (Or bytes crunched per second).
See that?
A Blackwell class GPU can crunch bytes 562 times faster than it can load them.
Put differently, to get the most out of such a chip, we should be doing 562 computations for every byte loaded.
Any more, and we have memory bandwidth sitting idle (e.g: without a KV-cache).
Any less, and we have compute cores sitting idle.
We're doing 2*B.
So, how many users should we serve to fully exhaust a B200's compute and bandwidth budget?
With a single NVIDIA B200 GPU, we should be serving 331 users concurrently to get the most out of our investment.
Of course, this is a theoretical ceiling.
In reality, VRAM is limited. We'll have to squeeze the model weights in there along with the huge KV-cache.
How many users can you serve realistically?
We'll assume a 32B dense model – about as much as a 192G chip
can comfortably support.
This could be a Gemma, Qwen, DeepSeek, whatever.
Different techniques and parameter sizes cancel out to yield roughly the same result, off by maybe a 5-10% margin.
Back to our problem: we have a 32B model.
This is 32*10^9 bytes, or 32GB, in VRAM.
Let's assume a context window of =200k tokens.
The input is –dimensional at every layer.
For each layer, we need to store bytes for a pair of K and V matrices.
A model of our size will typically have d=8192 and L=64. Giving us:
`
KV cache size = 2 * N * L * d
= 2 * 200_000 * 64 * 8196
= 210 GB (!!)`
That's more VRAM than our GPU has!
Here, I'll invoke another optimization that models of this size use: Grouped-Query-Attention. If attention was new to you, you may save this for future reading and rely on my claim that it cuts down the KV cache size by about 8x.
But if you're familiar with Multi-Head-Attention then GQA is simple: It shares the same KV-head across multiple Query heads. So for 64 query heads, we'll use a total of only 8 KV-heads; i.e: Q-heads 0-7 share the first KV-head, Q-heads 8-15 the next one, and so on.
With GQA our KV-cache is now at ~26GB *per chat sequence (or per user)*.
We're already using 32GB for weights,
so how many concurrent chat contexts can we store in the KV-cache in the remaining 160GB?
That's 160/26 = 6.
So about six chat's going parallely. That seems… low.
Optimizing for hundreds of users on a GPU.
Most contexts will never reach the 200k token limit,
even if that is the context window you advertise to customers.
Depending on your product, the median LLM-conversation can be anywhere between 4-40k tokens.
We can split the KV-cache into chunks, and then allocate those chunks to different users as their token use increases.
Conversation threads that are abandoned/cold can be flushed out of the cache.
This is what vLLM does with PagedAttention.
Depending on the median user activity,
you can serve anywhere between 40-60 users per Blackwell chip,
depending on what you assume for the conversation length.
Remember that the nature of your product matters too.
In most ChatGPT-style apps the user spends more time reading than prompting.
For a median chat session, a user will likely have 80% idle time.
Here, the GPU has a duty cycle of 20% (!).
So realistically, one chip can serve ~300-800 users comfortably depending on the style of app.
Of course, this won't hold if you're using some harness to feed the agent with data in a loop.
Tokens Per Second
Earlier, we saw that we can comfortably support 6 users at 100% duty cycle.
But what would be the speed observed by them?
Again, this is a direct consequence of our memory-to-compute ratio.
For a single forward pass, we'll move all the model weights + KV-cache from
VRAM to registers *once*.
Then, we'll do 2*B operations for every byte loaded.
So the total time spent is:
`
time spent moving data (in seconds)
= memory in GB / bandwidth in GBps
= 190GB / (8*10**3) GBps
= 0.02375 seconds
= 23.75 ms
time spent computing
= 190 * 2 * 6 / 4500 TFLOPs
= 0.5ms`
Since both happen in parallel,
the compute cores are idle 98% of the time.
Every 24ms, we generate B=6 tokens.
For 1s (=1000ms), we generate roughly 250 tokens for 6 users,
or about 40 tokens per user per second.
Assuming the LLM output is meant for reading
(unlike, say, building SQL queries in the background),
40 tokens per second is beyond most people's reading speed.
Dollar cost per user
This largely depends on whether you own or rent your hardware.
At $40,000 per B200, your lifetime cost per user is 40_000/num_users.
In the 100% duty cycle case (worst for cost), that's 6k$ per user.
Realistically, serving 500 users per GPU you'll spend a lifetime
cost of about $133 per user, plus the datacenter/upkeep bill.
If you rent the GPU, the cost is more straightforward.
At $3 per hour for a B200, your cost per user per hour is 3/num_users.
for num_users=500 you get a cost of about $0.006 per user per hour,
or $4.32 per month.
So as long as you charge them more than $4.32, your operating costs are covered.
As an AI company, you'll have more than one GPU (I hope).
So you'll be load balancing users across a cluster of GPUs where our equations change somewhat.
Sadly, we're out of space on our napki-
関連記事
[AINews] 今日特に大きな出来事はありませんでした
Latent Space は、GLM 5.2 が依然として注目されていると指摘しつつ、AIE WF 2026 の通常チケットが月曜日に完売すると発表しました。同サイト購読者向けに限定割引を提供し、参加者には Warp や Datadog などからのスポンサークレジットも付与されます。
米国がアンソロピックの「Fable 5」発売を禁止、しかし市場は動じず
米国政府は国家安全保障上の懸念から、アマゾンの研究者らがガードレール回避手法を発見したとして、アンソロピックに対し最新モデル「Fable 5」と「Mythos 5」の販売差し止めを命じた。サイバーセキュリティ研究者らはこの措置が危険だとする公開書簡に署名し、同社も他モデルでも同様の抜け道が存在すると指摘している。
社内データ分析エージェントの構築方法について
GitHub は、大規模なデータ組織が直面する自己完結型のデータアクセスと洞察提供の課題に対し、AI を活用した信頼性の高い解決策として、社内でデータ分析エージェントを構築したことを発表した。
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み