WavePP: High-Throughput Pipeline Parallel LLM Prefill under Prefix Reuse
Organizations: Baseten
Abstract
Pipeline parallelism can improve prefill throughput by processing multiple request chunks concurrently across different stages of the model. However, keeping the pipeline fully utilized requires efficient scheduling and request preparation. In systems where stages retain and evict cache state independently, a local cache hit does not guarantee that the same prefix can be reused across the pipeline. Here, coordination overhead can impede request admission cadence and thus reduce overall throughput. In this paper, we present WavePP, a prefill runtime built on top of TensorRT-LLM that addresses these challenges by overlapping request admission with pipeline execution. WavePP asynchronously finds a prefix that can be reused across all stages, protects the cached state, and reserves space for the remaining input while earlier requests continue to execute. It subsequently plans the chunk sizes of each request dynamically to maximize pipeline fill. Each stage then completes the local preparation before executing the request. In the same system and pipeline topology, WavePP improves TensorRT-LLM's prefill throughput in 37 of 40 tested settings on GLM 5.2 and MiniMax M2.7. At concurrency 128 with high cache reuse, these changes increase throughput by factors of 2.91 and 2.02, respectively. Across 28 Kimi K3 settings, WavePP also has the highest measured throughput in all 18 settings at concurrency eight or higher, compared with tensor/expert-parallel and pipeline-parallel baselines from TRT-LLM, SGLang, and vLLM.
Figures & tables
| GLM 5.2 | MiniMax M2.7 | ||||||
| Family | TRT-LLM | WavePP | TRT-LLM | WavePP | |||
| Short cold | 8 | 46,658 | 47,552 | +1.9% | 50,677 | 54,457 | +7.5% |
| 16 | 46,207 | 48,071 | +4.0% | 50,127 | 54,642 | +9.0% | |
| 32 | 45,730 | 47,864 | +4.7% | 49,596 | 54,615 | +10.1% | |
| Long cold | 8 | 41,839 | 43,456 | +3.9% | 37,146 | 40,388 | +8.7% |
| 16 | 41,610 | 43,310 | +4.1% | 37,051 | 40,363 | +8.9% | |
| Baseline | Parallel configuration | Benchmark configuration |
| vLLM TP8/EP8 | TP8/EP8 on eight GPUs | v0.28.0 with the FlashInfer TensorRT-LLM MoE path |
| SGLang TP8/EP8 | TP8/EP8 on eight GPUs | Same SGLang build, 16K prefill budget, and hybrid host-cache configuration as the SGLang PP8 arm |
| TRT-LLM TP8/EP8 | TP8/EP8 on eight GPUs | Same Kimi K3 engine family and shared kernel changes as WavePP; valid two-node tensor-parallel placement |
| vLLM PP8 | Eight-stage pipeline parallelism | v0.28.0 with a 16K packed-token budget and prefix caching enabled |
| SGLang PP8 | Eight-stage pipeline parallelism | 16K prefill chunks; 128 GiB/rank hybrid MLA+Mamba host cache; write-through offload, kernel I/O, and page-first loading |
| Family | Input tokens | Shared prefix | Request composition | Concurrency |
|---|---|---|---|---|
| Cold 65.5K | 65,536 | 0% | cold | 1, 4, 8, 16, 32 |
| Cold 131K | 131,072 | 0% | cold | 1, 4, 8, 16, 32 |
| Cold 262K | 262,144 | 0% | cold | 1, 4, 8, 16, 32 |
| Reuse 131K | 131,072 | 90% | seeded shared prefix | 1, 4, 8, 16, 32 |
| Reuse 262K | 262,144 | 90% | seeded shared prefix | 1, 4, 8, 16, 32 |
| Mixed | – | – | 75/25 warm-131K/cold-262K | 8, 16, 32 |
| Context, | vLLM TP8/EP8 | SGLang TP8/EP8 | TRT-LLM TP8/EP8 | vLLM PP8 | SGLang PP8 | WavePP | ||
|---|---|---|---|---|---|---|---|---|
| 65.5K, 1 | 23,330 | 20,378 | 22,976 | 20,361 | 16,691 | 22,089 | -5.3% | +8.5% |
| 65.5K, 4 | 23,922 | 22,215 | 23,524 | 41,554 | 39,926 | 37,467 | +56.6% | -9.8% |
| 65.5K, 8 | 23,917 | 22,194 | 23,490 | 41,980 | 40,458 | 43,007 | +79.8% | +2.4% |
| 65.5K, 16 | 23,925 | 22,215 | 23,537 | 42,242 | 40,852 | 44,746 | +87.0% | +5.9% |
| 65.5K, 32 | 23,925 | 22,213 | 23,536 | 42,456 | 41,180 | 44,643 | +86.6% | +5.2% |
| 131K, 1 | 21,430 | 19,810 | 21,380 | 23,030 | 21,014 | 20,699 | -3.4% | -10.1% |
| vLLM TP8/EP8 | SGLang TP8/EP8 | TRT-LLM TP8/EP8 | vLLM PP8 | SGLang PP8 | WavePP | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Context, | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 |
| 65.5K, 1 | 2.8 | 2.8 | 3.2 | 3.2 | 2.9 | 2.9 | 3.2 | 3.2 | 3.9 | 3.9 | 3.0 | 3.0 | +7.1% | +7.1% | -6.2% | -6.2% |
| 65.5K, 4 | 10.8 | 11.5 | 11.8 | 11.8 | 11.1 | 11.1 | 6.1 | 6.1 | 6.3 | 6.3 | 6.8 | 7.1 | -37.0% | -36.0% | +11.5% | +16.4% |
| 65.5K, 8 | 21.6 | 22.3 | 23.5 | 23.8 | 22.3 | 22.5 | 12.2 | 12.2 | 12.6 | 12.6 | 11.8 | 12.4 | -45.4% | -44.4% | -3.3% | +1.6% |
| 65.5K, 16 | 43.9 | 44.0 | 47.1 | 47.3 | 44.5 | 44.5 | 24.4 | 24.4 | 25.1 | 25.1 | 22.8 | 23.2 | -48.1% | -47.3% | -6.6% | -4.9% |
| 65.5K, 32 | 87.3 | 87.9 | 94.4 | 94.4 | 89.0 | 89.1 | 48.8 | 48.8 | 50.1 | 50.2 | 45.4 | 45.9 | -48.0% | -47.8% | -7.0% | -5.9% |
| Context, | vLLM TP8/EP8 | SGLang TP8/EP8 | TRT-LLM TP8/EP8 | vLLM PP8 | SGLang PP8 | WavePP | ||
|---|---|---|---|---|---|---|---|---|
| 131K, 1 | 155,002 | 127,746 | 142,607 | 43,197 | 41,022 | 56,810 | -63.3% | +31.5% |
| 131K, 4 | 167,165 | 172,924 | 183,856 | 130,420 | 134,161 | 124,682 | -32.2% | -7.1% |
| 131K, 8 | 173,271 | 173,266 | 186,690 | 171,714 | 228,012 | 255,406 | +36.8% | +12.0% |
| 131K, 16 | 173,510 | 172,581 | 185,931 | 212,477 | 249,227 | 262,740 | +41.3% | +5.4% |
| 131K, 32 | 173,780 | 172,847 | 186,064 | 219,649 | 253,844 | 289,096 | +55.4% | +13.9% |
| 262K, 1 | 133,140 | 122,545 | 131,382 | 49,238 | 45,127 | 64,674 | -51.4% | +31.3% |
| vLLM TP8/EP8 | SGLang TP8/EP8 | TRT-LLM TP8/EP8 | vLLM PP8 | SGLang PP8 | WavePP | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Context, | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 |
| 131K, 1 | 0.8 | 0.9 | 1.0 | 1.0 | 0.9 | 0.9 | 3.0 | 3.0 | 3.2 | 3.2 | 2.3 | 2.3 | +187.5% | +155.6% | -23.3% | -23.3% |
| 131K, 4 | 3.1 | 3.7 | 3.1 | 3.8 | 2.8 | 3.0 | 3.6 | 4.6 | 3.8 | 4.7 | 4.2 | 4.5 | +50.0% | +50.0% | +16.7% | -2.2% |
| 131K, 8 | 6.2 | 6.3 | 5.6 | 7.0 | 5.2 | 6.9 | 5.7 | 7.9 | 4.1 | 6.2 | 3.7 | 5.5 | -28.8% | -12.7% | -9.8% | -11.3% |
| 131K, 16 | 12.4 | 12.5 | 12.0 | 12.7 | 10.5 | 12.3 | 8.9 | 12.4 | 8.0 | 9.3 | 7.3 | 9.6 | -30.5% | -22.0% | -8.8% | +3.2% |
| 131K, 32 | 23.9 | 24.8 | 23.8 | 24.7 | 22.6 | 22.8 | 17.9 | 20.3 | 15.9 | 16.6 | 13.2 | 17.0 | -41.6% | -25.4% | -17.0% | +2.4% |
| vLLM TP8/EP8 | SGLang TP8/EP8 | TRT-LLM TP8/EP8 | vLLM PP8 | SGLang PP8 | WavePP | |||
|---|---|---|---|---|---|---|---|---|
| 8 | 40,797 | 38,986 | 41,945 | 53,129 | 58,079 | 61,063 | +45.6% | +5.1% |
| 16 | 40,790 | 39,062 | 42,064 | 53,551 | 58,468 | 61,436 | +46.1% | +5.1% |
| 32 | 40,849 | 39,074 | 41,695 | 53,678 | 58,348 | 61,190 | +46.8% | +4.9% |
| vLLM TP8/EP8 | SGLang TP8/EP8 | TRT-LLM TP8/EP8 | vLLM PP8 | SGLang PP8 | WavePP | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | p50 | p95 | |
| 8 | 32.3 | 45.2 | 33.6 | 47.5 | 23.2 | 46.6 | 24.1 | 26.4 | 22.2 | 31.3 | 21.0 | 25.6 | -9.5% | -43.4% | -5.4% | -3.0% |
| 16 | 64.0 | 77.6 | 67.2 | 67.9 | 62.1 | 66.5 | 48.1 | 50.7 | 44.3 | 44.7 | 41.9 | 51.1 | -32.5% | -23.2% | -5.4% | +14.3% |
| 32 | 128.0 | 141.6 | 133.9 | 148.7 | 125.2 | 142.4 | 96.3 | 115.9 | 88.8 | 98.1 | 83.8 | 109.7 | -33.1% | -22.5% | -5.6% | +11.8% |
| Offered rate (req/s) | TRT-LLM TP8/EP8 | WavePP | Difference (pp) ( better) |
| 0.500 | 82% | 100% | +18 |
| 0.625 | 76% | 92% | +16 |
| 0.750 | 73% | 91% | +18 |
| 0.875 | 80% | 88% | +8 |
| 1.000 | 83% | 97% | +14 |
| Rung | Configuration | Added mechanism |
|---|---|---|
| R0 | TRT-LLM TP8/EP8 | Tensor-parallel reference |
| R1 | Naive re-implementation | Lockstep request preparation |
| R2 | + wave admission/transport | Independent context-wave execution |
| R3 | + lease admission | Exact reuse and capacity ownership |
| R4 | + MPU | Planner-driven packing, adaptive wave sizing, and progress deadline |