DeepSeek V3/R1 Inference Efficiency (3): Generalizing the Decode Configuration
Originally published in Chinese on Zhihu, March 30, 2025.
This is part 3 of 3
Part 1 estimated a throughput ceiling from the V3 paper; part 2 reverse-engineered DeepSeek's published EP144 deployment. This part generalizes that result across device counts, batch sizes and hardware.
1. Introduction
With the reverse-engineering done, there is enough data and method to answer two questions:
- How does the DP-EP device count affect throughput?
- How would other hardware run DeepSeek V3/R1?
Prefill is comparatively simple, so this post covers only the generalization of decode.
TL;DR
While this was being written, zarbot published a theoretical estimation method for DeepSeek V3 (DeepSeek-V3/R1 推理效率分析 v0.17), iterating rapidly. It is well suited to estimating performance across hardware platforms. Pure theory carries some error in the MFU of mm / grouped mm / bmm / attention and in modelling overlap, but for cross-platform estimation in the absence of a real implementation it is very useful, and worth recommending.
This post takes a different approach: integrating existing performance libraries — DeepGEMM, FlashMLA and torch — into a simulator that measures directly, with the overlap modelled in detail, which should make the results comparatively accurate. The code is open source here. To try it on non-Hopper hardware, adapt your own operator benchmark library to the test script's format and the simulation runs automatically.
Hardware: H800 80G, H20 96G.
Parallelism: Attention DP + MoE EP; Attention TP+DP + MoE EP.
Overlap: two-microbatch overlapping (DeepSeek's own scheme); single-batch compute-communication overlapping.
Full results and analysis are in section 4.
2. Generalizing the H800 DP-EP configuration
Correcting the weight-conservation identity
- Per-GPU batch size:
- Per-microbatch batch size:
- 32 extra experts per layer:
GB - Extra shared experts in total:
GB - Per FlashMLA, the KV cache is BF16 rather than FP8, so per-token storage is
KB.
The corrected H800 weight identity is
which simplifies to
giving an upper bound on
Enumerating over H800 device counts
- An FP8 KV cache raises
substantially, so its throughput is worth estimating. (Assume FlashMLA's FP8 dequant cost is negligible and approximate with FlashMLA BF16 attention performance.) - Either the microbatch-1 or the microbatch-2 overlap pipeline can be used — see below.
The largest power of two below

2.1 Dense GEMM performance across shapes
From DeepGEMM's dense GEMM curve, FP8 peaks at only 1400 TFLOPS — 70% MFU — and saturates earlier than BF16.
Because of the memory constraint,

Dense GEMM efficiency depends only on

2.2 MLA attention performance across batch sizes
FlashMLA peaks at just over 500 TFLOPS. I have not studied the FlashMLA implementation closely; this may relate to the partial warp pipeline discussed in ChiveArchitect's per-GPU throughput estimates for DeepSeek 671B across chips.

2.3 Device count and all-to-all communication
The communication side deserves some discussion.
- On H800 the ConnectX-7 has a theoretical 50 GB/s, measured at 39 GB/s, in a per-GPU-per-NIC topology.
- The all-to-all considered here is always bound by inter-device communication. On H800, intra-machine NVLINK gives 160 GB/s / 7 = 29 GB/s, below the 40 GB/s inter-machine figure, so with two or fewer machines the intra-node all-to-all could bind instead. That is a relatively unlikely case — 7 experts inside the machine, 1 across — so it is ignored here. Two extensions are worth noting:
- If the NIC moves to something like ConnectX-8 (an estimated 80 GB/s measured) while intra-machine stays at 160 GB/s, intra-node all-to-all can become slower than inter-node at small node counts. Expert locality requirements then relax, and intra- and inter-machine traffic have to be balanced to optimize the all-to-all. Out of scope here.
- On other card types — PCIe cards, whether behind a PCIe switch or an AMD CPU direct connection — intra-machine all-to-all easily becomes the global bottleneck. Throughput will not be good in that case; the network is the thing to upgrade. Also out of scope.
- Across device counts from 16 to 288, the volume sent depends on
: under intra-device parallelism, with only 4 nodes each token sends at most 3 duplicates, and with 2 nodes at most 1.

2.4 Device count and batch size in the routed-expert GEMM
The parameter combinations are too numerous to list; a representative subset:

Some trends are visible. The smaller the device count, the larger the per-GPU m_per_group means higher arithmetic intensity and higher TFLOPS.



TFLOPS at n = 4096, k = 7168 across (num_group, m_per_group)
2.5 Batch size and memory ops
Empirical values from prefill are reused directly here. Ideally, latency would be scaled by bandwidth ratio across card types, but these terms are small and fiddly, and later estimates progressively ignore them — the data below shows that whether these memory-bound operators are counted makes very little difference to the order of magnitude.

2.6 Assembling the pipeline
Wrapping the components together gives the following:

How should the pipeline be assembled?
2.6.1 Two-microbatch overlapping
The first option is the scheme DeepSeek uses, which assumes attention dominates the compute:
| Module | GFLOPs | Share of FLOPs |
|---|---|---|
| MLA attention | 50% | |
| O projection | 8% | |
| Routed up & gate | 17% | |
| Routed down | 8% |
Combine is also relatively expensive. So the long attention is overlapped with combine, and dispatch is overlapped naturally with the smaller QKV and shared-expert operators.
Case 1:

2.6.2 Single-batch compute-communication overlapping
Two microbatches has side effects: splitting the batch lowers arithmetic intensity, and TPOT has to wait for both microbatches to finish, which is not favourable for latency.
An alternative is to overlap the down GEMM with combine within a single batch.
Case 2:
With two microbatches, communication on the critical path is essentially hidden, leaving compute and memory: a single layer's microbatch forward is

With a single microbatch: assume tiling can overlap the combine communication with the down GEMM's compute (the O + gate against dispatch overlap is hard to write, so assume it cannot overlap). This works only when combine and the down GEMM are comparable — here the down GEMM is 56 µs against 64 µs of combine, so a good deal overlaps and the communication is hidden. A single layer's microbatch forward is

Case 3:
Since two microbatches implies
The underlying reason: dispatch and combine are not especially expensive here, so accepting some bubble avoids both the loss of arithmetic intensity and the latency penalty of two microbatches. Where combine is long, throughput would visibly drop instead.

2.6.3 The general form
The pipeline analysis generalizes to the following.
1) Two-microbatch overlapping
2) Single-batch compute-communication overlapping
2.7 H800 throughput
Partial H800 throughput data follows. (The
1) Two-microbatch overlapping

2) Single-batch compute-communication overlapping

Computing memory-op durations is fiddly. Drawing them into the overlap diagrams illustrates overlap efficiency more clearly, but their share really is small enough to ignore. So how far off is an estimate that counts only GEMM + attention + all-to-all?
1) Two-microbatch overlapping

2) Single-batch compute-communication overlapping

Comparing before and after, GEMM + attention + all-to-all captures the model's real latency and throughput well enough. Subsequent estimates therefore drop the memory-op terms, which simplifies the model towards something general.
3.1 The compute required to meet the latency target
Total compute FLOPs for a single layer and single microbatch:
| Module | GFLOPs | Share of FLOPs |
|---|---|---|
| MLA attention | 50% | |
| O projection | 8% | |
| Routed up & gate | 17% | |
| Routed down | 8% |
MLA attention runs in BF16 and the other GEMMs in FP8. Assuming MFU = 100%, meeting a 20 tokens/s target requires:
H800
giving
H20
giving
Taking the maximum
GPU Type: H800-80
Device number: (16, 24, 32, 48, 72, 96, 144, 288)
Max batch size per GPU: (133, 220, 264, 308, 337, 352, 366, 381)
GPU Type: H20-96
Device number: (16, 24, 32, 48, 72, 96, 144, 288)
Max batch size per GPU: (231, 318, 362, 406, 435, 449, 464, 478)| Device count | H800, FP8 KV cache | H20, FP8 KV cache | H20, BF16 KV cache |
|---|---|---|---|
| 16 | 100% | 26% | 52% |
| 24 | 100% | 19% | 38% |
| 32 | 100% | 16% | 32% |
| 48 | 100% | 15% | 30% |
| 72 | 100% | 14% | 28% |
| 96 | 100% | 13% | 26% |
| 144 | 100% | 13% | 26% |
| 288 | 100% | 12% | 24% |
Under a latency constraint, scaling H20 to buy KV cache is useless — the memory cannot be effectively utilized in the first place.
For low-compute cards, TP is needed to relax the latency constraint and buy better scaling. Since attention plus O projection accounts for 58% of the compute, those are the matrices to shard.
3.2 MLA (TP-DP) + MoE EP
The MoE expert GEMM shapes are relatively small, so TP is not advisable there. For modelling simplicity and communication efficiency, TP on the attention is confined to within a machine.
MLA is sharded on the head dimension of Q, which affects the matrix shapes as:
The compute matrix from 3.1, under TP:
| Module | TP=1 | TP=2 | TP=4 | TP=8 |
|---|---|---|---|---|
| MLA attention | 1.39 | 0.70 | 0.35 | 0.17 |
| O projection | 0.23 | 0.12 | 0.06 | 0.03 |
| Routed up & gate | 0.47 | 0.47 | 0.47 | 0.47 |
| Routed down | 0.24 | 0.24 | 0.24 | 0.24 |
| Others | 0.46 | 0.46 | 0.46 | 0.46 |
| Total | 2.79 | 1.98 | 1.57 | 1.37 |
(All figures in GFLOPs, scaled by
At TP = 8 the compute ceiling updates to:
H800 —
H20 —
3.2.1 Updating the memory-conservation identity
Of the 14B dense weights, MLA accounts for approximately
Per GPU under TP, the MLA parameter count is
so across
which gives the updated memory utilization:
GPU Type: H20-96
TP= 1 Device Number: [16, 24, 32, 48, 72, 96, 144, 288]
Max batch size per GPU: [231, 318, 362, 406, 435, 449, 464, 478]
TP= 2 Device Number: [16, 24, 32, 48, 72, 96, 144, 288]
Max batch size per GPU: [240, 328, 371, 415, 444, 459, 473, 488]
TP= 4 Device Number: [16, 24, 32, 48, 72, 96, 144, 288]
Max batch size per GPU: [245, 332, 376, 420, 449, 463, 478, 493]
TP= 8 Device Number: [16, 24, 32, 48, 72, 96, 144, 288]
Max batch size per GPU: [247, 335, 378, 422, 451, 466, 480, 495]| Device count | H20, FP8 KV cache | H20, BF16 KV cache |
|---|---|---|
| 16 | 65% | 100% |
| 24 | 48% | 96% |
| 32 | 43% | 86% |
| 48 | 38% | 76% |
| 72 | 36% | 72% |
| 96 | 35% | 70% |
| 144 | 34% | 68% |
| 288 | 33% | 66% |
3.2.2 Updating the token-dispatch formulas
With TP enabled, a TP group shares tokens, so the redundancy between TP ranks has to be removed when counting MoE EP tokens.
Routed expert compute:
Routed all-to-all volume: the all-to-all within a TP group can be amortized across its GPUs, so each GPU only sends the activations of
3.2.3 Updating communication and the pipeline
Attention TP requires an all-reduce after the O projection, with BF16 traffic of
| tp=2 | tp=4 | tp=8 | |
|---|---|---|---|
| 8 | 1 | 1 | 1 |
| 16 | 1 | 2 | 2 |
| 32 | 3 | 4 | 5 |
| 64 | 5 | 8 | 9 |
| 128 | 11 | 16 | 19 |
| 256 | 21 | 32 | 37 |
At small volumes this is purely latency-bound, so an empirical floor of around 5 µs applies.
Against the O projection GEMM's own duration on H800:
| tp=2 | tp=4 | tp=8 | |
|---|---|---|---|
| 8 | 31 | 17 | 9 |
| 16 | 30 | 16 | 9 |
| 32 | 26 | 14 | 8 |
| 64 | 25 | 14 | 7 |
| 128 | 26 | 14 | 8 |
| 256 | 31 | 17 | 11 |
At large
Single-batch compute-communication overlapping:

Two-microbatch overlapping:

The overlap formulas update accordingly. Note the introduction of effective throughput: with
1) Two-microbatch overlapping
2) Single-batch compute-communication overlapping
4. H800 and H20 results
Test environment: CUDA 12.6, PyTorch 2.4, Python 3.10.
Simulation results are generated for Attention DP + MoE EP and Attention TP+DP + MoE EP under both pipeline schemes.
- Yellow marks the best throughput at each device count that roughly meets a 20 tokens/s user latency.
- Orange marks the best online configuration across all device counts meeting that latency.
- Green marks maximum FP8 KV cache throughput ignoring the latency constraint.
- Blue marks maximum BF16 KV cache throughput ignoring the latency constraint.
Full results are here.
4.1 H800
- DP-EP gives the best offline throughput; enabling attention TP hurts it.
- Best offline throughput with BF16 KV cache: 2844 tokens/s per GPU, from two-microbatch overlapping at DP288-EP288,
. - Best offline throughput with FP8 KV cache: 3121 tokens/s per GPU, from two-microbatch overlapping at DP288-EP288,
, or at DP48-EP48, . - Best online throughput with FP8 KV cache (meeting ~20 tokens/s): 2909 tokens/s, from single-batch compute-communication overlapping at DP24-EP24,
. - Best online throughput with BF16 KV cache: 2844 tokens/s, from two-microbatch overlapping at DP288-EP288,
.

Two-microbatch overlapping, best configurations — H800

Single-batch overlapping, best configurations — H800
As expected, at
Beyond DeepSeek's own EP144, the marginal return from going to EP288 is fairly limited; the full results are there to choose from. Realizing the FP8 KV cache means writing an FP8-KV-cache MLA kernel; realizing single-batch overlapping means writing the down-GEMM / combine all-to-all overlap. Both require some infrastructure work, though neither is difficult.
4.2 H20
- DP-EP again gives the best offline throughput, and attention TP hurts it. But on a low-compute card like H20, attention TP helps reach a better TPOT at the same node count, which is what meeting the SLO requires. Note that too much TP reduces effective per-GPU throughput and lowers overall throughput; TP = 2 measured as the reasonable online configuration.
- Best offline throughput with BF16 KV cache: 969 tokens/s per GPU, from two-microbatch overlapping at DP72-EP72,
. - Best offline throughput with FP8 KV cache: 980 tokens/s per GPU, from two-microbatch overlapping at DP72-EP72,
. - Best online throughput, either KV cache dtype (meeting ~20 tokens/s): 820 tokens/s, from single-batch compute-communication overlapping at DP48-EP48 with
, or TP2-DP24-EP48 with .

Two-microbatch overlapping, best configurations — H20

Single-batch overlapping, best configurations — H20
5. Conclusion
That completes the goal of the series: generalizing DeepSeek R1's deployment configuration. Small instance groups can run single-batch overlapping themselves, or adopt an FP8 KV cache to raise throughput, which opens up a considerably wider search space of deployment options. DeepSeek's published configuration is not the only choice, and an instance group as large as DP144-EP144 is not required for good online service — trading away some throughput buys a deployment that is more flexible and simpler to run.
H20's throughput efficiency comes out at roughly 30% of H800's, which is the figure to use when working out TCO. I do not have heterogeneous hardware to hand, but this tooling should adapt readily to any chip with a basic operator library, and produce reasonable simulated figures from it.
The post involves a great deal of arithmetic; corrections are welcome.