DeepSeek V3/R1 Inference Efficiency (1): A Back-of-the-Envelope Decoding Throughput Ceiling
Originally published in Chinese on Zhihu, March 17, 2025.
This is part 1 of 3
The series follows the analysis as it developed: part 1 is a coarse order-of-magnitude estimate from the V3 paper's parameters alone; parts 2 and 3 refine it quantitatively against the figures DeepSeek subsequently published. Precision improves substantially across the three, so anyone interested in the topic should read through to part 3 — several questions raised about the accuracy of part 1 are analysed and corrected there.
DeepSeek published an overview of its V3/R1 inference system. Before those numbers were available, and without the three hundred–odd GPUs needed to run the experiment properly — large distributed MoE inference had not been anticipated internally, and the scale-out capability of SGLang and vLLM was still being built — we had made some theoretical estimates, as an attempt to reverse-engineer how DeepSeek's deployment must be configured.
What follows is that estimate, tidied up. A number of arithmetic errors were caught in discussion with colleagues in the field, which is reflected here.
Acknowledgements. The initial batch-size discussion came out of conversations with Changcheng Tang and Xiangcheng Liu from Kuaishou's LLM inference team; Yuliang Liu reviewed some of the conclusions. The compute and communication ceilings were reviewed and corrected by Mingran Wang of SambaNova, and the network-ceiling method follows zarbot's approach.
Parameters
MLA:
, - KV compression dim
, query compression dim ,
Expert — three GEMMs (up, down, gate):
DeepSeek-V3 has 671B parameters total, of which 37B activate per token. It has 61 transformer layers: the first 3 are non-MoE, and the remaining 58 have their FFN expanded into an MoE of 1 shared expert plus 256 routed experts, with
Dense vs. sparse parameter split
A single expert's weights are

DeepSeek-V3 parameter distribution
Working backwards from the 37B activated per token:
So as approximate weight figures:
- per expert: 44M = 42 MB
- dense part: 14B ≈ 13 GB
- all experts: 657B ≈ 612 GB
Average sequence length
Assumptions on the input/output length distribution:
- DeepSeek V3: 1k + 1k on average, matching NVIDIA's official benchmark convention.
- DeepSeek R1: 1k + 5k on average, consistent with the figure DeepSeek published — "the average KV cache length per output token is 4989."
Choosing a device count that reaches compute bound
The most basic deployment of V3/R1 is 8-way TP within one machine, which needs 625 GB for weights — so the entry configuration is typically H20 96G × 8 or H800 80G × 16. In both, the KV cache capacity left over is very small, which drives down both the attention QKV GEMM batch size and the MoE batch size. The MoE experts end up firmly memory-bound, even latency-bound, which is hostile to continuous batching. Raising batch size is therefore the basic requirement for throughput, and scaling out across machines — lowering the per-GPU weight footprint — is the basic means of doing so.
TP is unhelpful for MLA's KV cache: MLA compresses multiple heads into a single hidden vector, so the cache cannot be split by head within a TP group, and every GPU stores a redundant copy. Scaling out therefore starts from Attention DP + TP/EP on the MoE. Accounting for cross-device communication efficiency, Attention DP + MoE EP is the more workable of the two.
The V3 paper uses 40 × 8 H800 for decode nodes: attention as 4-way TP+SP plus 80-way DP, MoE as 320-way EP. Since TP+SP stays within a machine and is not the binding constraint on batch or communication, the rest of this post assumes Attention DP + MoE EP for simplicity.
Which brings the basic question:
What is the minimum number of H800s needed for the MoE experts to become compute-bound?
To keep the estimate tractable, assume no redundant experts, and set aside the shared expert and the three dense layers.
1. The memory constraint
- per-GPU sequence length:
(typically 1 when decoding) - average sequence length per request:
- per-GPU MLA batch size:
- per-expert batch size:
- GPU count:
- expert count:
- Per-GPU activation footprint: for
this is roughly a constant multiple of — write it — dominated by MLA activations. SGLang's activation memory management is currently poor; measured with spread over 1k–8k, activations stay under 8 GB. (A smaller activation figure does not change the order of magnitude of anything below.) - MLA KV cache per token:
KB in FP8. (SGLang and similar frameworks currently only support a BF16 KV cache; the ceiling here is computed for FP8 storage.) - Assume
, so each GPU holds experts on average.
The weight-conservation identity is then
Substituting the empirical 8 GB activation assumption:
The ranges this admits for
The formula assumes experts are stored without redundancy (612 GB), so
. It requires
, i.e. the tokens held per GPU must satisfy . - Even with zero activation the ceiling is only
. - Condition 1 gives a tighter bound,
, for a ceiling of . - Neither changes the order of magnitude.
For V3, with
: . For R1, with : . - Even with zero activation the ceiling is only
, so .
Conclusion 1. For the Q/K/V projection matrices, at long sequence lengths no amount of H800 scale-out reaches the FP8 compute saturation point. (DeepGEMM results put the empirical FP8 saturation point for H800 at
2. The constraint for MoE to reach compute bound
The MoE receives
so
For V3 at
For R1 at
Conclusion 2. On H800, the MoE device count need not be large for V3 — both
Estimating the throughput ceiling
Optimizing for throughput, we want a batch large enough to be compute-bound, which makes it unlikely that memory bandwidth is the overall limit — leaving compute or communication.
1. The compute-bound ceiling
Estimating decode FLOPs: outside MLA, the usual
Decode MLA normally runs in absorbed form:
- FLOPs are
; substituting MLA's parameters, FLOPs. - So decode compute is about
GFLOPs. - Aggregate FP8 compute is
TFLOPS on H800 and TFLOPS on H20.
For V3 at
For R1 at
2. The network-bound ceiling (zarbot's method)
Per token the payload is 7168 B, against 50 GB/s of inter-node RDMA bandwidth; a single dispatch across 61 layers and 9 experts totals about 4 MB. zarbot folds in an all-reduce for a total of 8 MB and concludes a per-GPU ceiling of 6000 tokens/s. But under DP+EP the DP portion carries no traffic — nothing is sent during the DP stage — so what remains is dispatch plus combine, also 8 MB, or 12 MB if combine is BF16. At 50 GB/s of RDMA bandwidth (40 GB/s in practice) that supports roughly 5000 tokens/s per GPU in FP8, or 3333 in BF16.
Two refinements worth noting.
zarbot's 9-expert figure assumes decode uses EP320 for minimum latency, leaving only 8 experts per node; estimating traffic at 9 experts is probably still the better approximation, given hop count and balance.
If communication is arranged to minimize inter-node bandwidth — as in training, where a token can be capped at 4 nodes, communicating first and duplicating within the device — then only 4 nodes' worth of traffic counts. More precisely, with the first 3 transformer layers non-MoE, a single dispatch is 58 layers × 4 experts ≈ 1.6 MB. With combine in FP8 that is 3.2 MB, or 4.8 MB in BF16; at 40 GB/s effective RDMA bandwidth, the per-GPU ceiling becomes 12800 tokens/s for FP8 combine and 8500 tokens/s for BF16. This raises the communication ceiling considerably.
Taking compute and communication together, without MTP, R1 on EP256 H800 in FP8 has a per-GPU ceiling of 3300 tokens/s (BF16 combine) to 5000 tokens/s (FP8 combine); H20 sits around 1600 tokens/s.
Two caveats.
- The network constraint is straightforward to estimate from measured bandwidth. Where compute is the binding constraint, MFU losses have to be accounted for — 60–70% of the figure is a realistic estimate, which puts H20 nearer 1000 tokens/s.
- H800 being network-bound presupposes its compute ceiling is high enough. Double the network bandwidth, or account for H800's very low MFU, and compute may bind first. The general principle holds: the narrowest pipe sets the ceiling.
The latency constraint
Take a 10 ms latency budget. Estimating from the per-iteration memory traffic of the experts against aggregate bandwidth, we need
which gives
Against the 20 tokens/s per user SLO common in commercial MaaS: at full batch this is equivalent to the time to load 80 GB once, at minimum 80 GB / 3350 = 24 ms. At batch sizes large enough to be compute-bound this rises. At small batch, a single expert matrix read is only
There is a trade-off here between memory-bound and compute-bound operation: scale out far enough to bring batch-size-1 latency down, then find the sweet spot in device count that maximizes batch size subject to a 50 ms TPOT constraint.
Summary
For reference, the figures DeepSeek published:
Total output tokens: 168B. Average output rate 20–22 tps; average KV cache length per output token, 4989.
Average per-H800 throughput: for prefill, roughly 73.7k tokens/s input (including cache hits); for decode, roughly 14.8k tokens/s output.
That is 1.85k tokens/s per GPU — 56% of the 3300 tokens/s estimated above for BF16 combine (per DeepEP), while holding 20–22 tokens/s per user. Reaching 56% of the theoretical ceiling under a latency constraint is, in my view, a very strong system result, assuming MTP is not in play.
Plenty of detail remains in trading latency against throughput — whether placing more experts per GPU would raise the network-bound ceiling, for instance, and what else is available to tune.