<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kirill Bespalov</title>
    <description>The latest articles on DEV Community by Kirill Bespalov (@kbespalov).</description>
    <link>https://dev.to/kbespalov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4198649%2F56455da1-3c12-4f16-90a8-368bc6d11326.png</url>
      <title>DEV Community: Kirill Bespalov</title>
      <link>https://dev.to/kbespalov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kbespalov"/>
    <language>en</language>
    <item>
      <title>DeepSeek V4.1 Flash on 8 B300: vLLM vs DeepInfer, 600K+ tokens/s</title>
      <dc:creator>Kirill Bespalov</dc:creator>
      <pubDate>Wed, 21 Oct 2026 15:04:21 +0000</pubDate>
      <link>https://dev.to/kbespalov/deepseek-v41-flash-on-8xb300-vllm-vs-deepinfer-600k-tokenss-3jl9</link>
      <guid>https://dev.to/kbespalov/deepseek-v41-flash-on-8xb300-vllm-vs-deepinfer-600k-tokenss-3jl9</guid>
      <description>&lt;p&gt;DeepSeek has open-sourced DeepInfer, the engine behind its own production service. We put it head to head with vLLM on a single 8×B300 node running DeepSeek-V4.1-Flash-1017, and pushed both to the limit on output tokens and on prefill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; on one node vLLM is &lt;strong&gt;2.0× faster on decode&lt;/strong&gt; (1K → 1K), &lt;strong&gt;4.3× at 8K → 1K&lt;/strong&gt;, and &lt;strong&gt;9× on prefill&lt;/strong&gt;. It peaks at &lt;strong&gt;658K prefill tokens/s&lt;/strong&gt; and &lt;strong&gt;55–65K output tokens/s&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frlr0rymdu4ifwlyvnugb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frlr0rymdu4ifwlyvnugb.png" alt="vLLM vs DeepInfer on 8×B300" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The engines
&lt;/h2&gt;

&lt;p&gt;Both run the same model with mostly the same kernels (FlashMLA, DeepGEMM, DeepEP) and scale it the same way: attention replicated per GPU, experts sharded across GPUs. The difference is scope.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;vLLM&lt;/th&gt;
&lt;th&gt;DeepInfer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Models&lt;/td&gt;
&lt;td&gt;Hundreds&lt;/td&gt;
&lt;td&gt;DeepSeek-V4.1-Flash only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware&lt;/td&gt;
&lt;td&gt;NVIDIA, AMD, TPU…&lt;/td&gt;
&lt;td&gt;NVIDIA SM100, Huawei Ascend 950&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interface&lt;/td&gt;
&lt;td&gt;OpenAI-compatible server&lt;/td&gt;
&lt;td&gt;Python offline API (&lt;code&gt;LLM.generate&lt;/code&gt;), no server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install&lt;/td&gt;
&lt;td&gt;Docker / pip&lt;/td&gt;
&lt;td&gt;Build from source (CUDA 13.1+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Highlights&lt;/td&gt;
&lt;td&gt;Prefix caching, structured outputs, LoRA, disaggregated prefill&lt;/td&gt;
&lt;td&gt;DSpark speculative decoding, batch-invariant inference, deterministic sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built for&lt;/td&gt;
&lt;td&gt;Any scale&lt;/td&gt;
&lt;td&gt;4 GPUs per prefill group, 64 per decode group&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPUs:&lt;/strong&gt; 8× NVIDIA B300 SXM6, 275 GB HBM3e each, NVLink 5&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; DeepSeek-V4.1-Flash-1017, 476 GB (FP4 experts, FP8 the rest, two Engram tables)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;vLLM:&lt;/strong&gt; 0.31.1rc1, B300 recipe, DEP8, 256 seqs per rank, DSpark with 5 draft tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepInfer:&lt;/strong&gt; commit 8b16149, EP8 × DP8, DSpark with 5 draft tokens, offline API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load:&lt;/strong&gt; &lt;code&gt;vllm bench serve&lt;/code&gt;, random-token prompts, fixed output length; DeepInfer got the same prompts in-process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Random prompts are the worst case for speculative decoding (19% draft acceptance at 1K, 12% at 8K), so every decode number here is a floor.&lt;/p&gt;

&lt;h2&gt;
  
  
  How DEP8 lays the model out
&lt;/h2&gt;

&lt;p&gt;The model is MoE: 384 routed experts + 1 shared per layer, 6 per token. vLLM's recipe runs it as DEP8: each GPU has its own attention and KV cache and holds 48 experts; tokens travel to their experts over NVSwitch every MoE layer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fobrnnb40sqjkkmohg214.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fobrnnb40sqjkkmohg214.png" alt="DEP8 layout on 8×B300" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memory is not the bottleneck: weights take 46 GiB per GPU and the KV cache gets 160 GiB (room for ~52M tokens per rank). The real limit is 256 running sequences per rank, 2,048 per node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flntn8rfabv12qsef9pxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flntn8rfabv12qsef9pxd.png" alt="Memory of one B300" width="799" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  vLLM at full load
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prefill&lt;/strong&gt; (one output token per request): 658K tokens/s with 8K prompts, about 82K per GPU.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8qa7n7azsva2lqnx5o3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8qa7n7azsva2lqnx5o3p.png" alt="vLLM prefill" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decode&lt;/strong&gt; with 2,048 concurrent requests: 65.0K output tokens/s with short prompts, 55.0K at 1K → 1K (29 ms per token).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flgy07j29vxny9rghihdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flgy07j29vxny9rghihdx.png" alt="vLLM decode" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;In → Out&lt;/th&gt;
&lt;th&gt;Concurrent&lt;/th&gt;
&lt;th&gt;Output tok/s&lt;/th&gt;
&lt;th&gt;Total tok/s&lt;/th&gt;
&lt;th&gt;TPOT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;128 → 1K&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;64,990&lt;/td&gt;
&lt;td&gt;73,114&lt;/td&gt;
&lt;td&gt;24.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1K → 1K&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;54,985&lt;/td&gt;
&lt;td&gt;109,969&lt;/td&gt;
&lt;td&gt;28.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8K → 1K&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;29,500&lt;/td&gt;
&lt;td&gt;265,496&lt;/td&gt;
&lt;td&gt;52.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2K → 128&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;19,753&lt;/td&gt;
&lt;td&gt;335,801&lt;/td&gt;
&lt;td&gt;74.4 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One gotcha: our first run made only 37.2K tok/s at 1K → 1K because CUDA graphs were captured only up to 1,536 tokens. Under load, steps mix decode with prompt chunks and every DP rank pads to the largest, so those steps ran without graphs. Capturing graphs up to 8,192 tokens brought it to 55.0K.&lt;/p&gt;

&lt;h2&gt;
  
  
  DeepInfer on one node
&lt;/h2&gt;

&lt;p&gt;Getting it running took longer than benchmarking it: source build with NVCC 13.1+, and it needs an RDMA device even on a single node (NCCL GPU-initiated networking for Engram rows).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq42p57z7sat2v4zygt97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq42p57z7sat2v4zygt97.png" alt="DeepInfer vs vLLM decode" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhb9orf0ygz3bikpvbdrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhb9orf0ygz3bikpvbdrb.png" alt="DeepInfer vs vLLM prefill" width="799" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;In → Out&lt;/th&gt;
&lt;th&gt;Concurrent&lt;/th&gt;
&lt;th&gt;DeepInfer&lt;/th&gt;
&lt;th&gt;vLLM&lt;/th&gt;
&lt;th&gt;vLLM ÷ DeepInfer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1K → 1K&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;27,906&lt;/td&gt;
&lt;td&gt;54,985&lt;/td&gt;
&lt;td&gt;2.0×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1K → 1K&lt;/td&gt;
&lt;td&gt;4,096&lt;/td&gt;
&lt;td&gt;26,294&lt;/td&gt;
&lt;td&gt;55,506&lt;/td&gt;
&lt;td&gt;2.1×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8K → 1K&lt;/td&gt;
&lt;td&gt;2,048&lt;/td&gt;
&lt;td&gt;6,933&lt;/td&gt;
&lt;td&gt;29,500&lt;/td&gt;
&lt;td&gt;4.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32K → 1 (prefill)&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;64,847&lt;/td&gt;
&lt;td&gt;589,924&lt;/td&gt;
&lt;td&gt;9.1×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;DeepInfer's own benchmark agrees (66K prefill tok/s per node), so it's not our harness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the gap?&lt;/strong&gt; DeepSeek benchmarks DeepInfer with prefill on 4 GPUs and decode on 64 GPUs, each in one NVLink domain. That's a rack, not a server, with prefill and decode on separate machines. The pieces that hold such a deployment together (KV cache system, P/D disaggregation, load balancing) aren't in the open-source release. On one node DeepInfer has to do everything at once, which is exactly what vLLM's recipe is built for. So read this as "DeepInfer on one node", not a verdict on its kernels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which engine, when
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API for users on one or a few nodes:&lt;/strong&gt; vLLM. 2× decode, 9× prefill, and a ready OpenAI-compatible server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any model other than DeepSeek-V4.1-Flash:&lt;/strong&gt; vLLM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible offline generation (RL rollouts, evals, synthetic data):&lt;/strong&gt; try DeepInfer for batch invariance and deterministic sampling, but measure throughput on your shapes first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rack-scale NVLink (GB200/GB300 NVL72):&lt;/strong&gt; look at both. DeepInfer is how DeepSeek serves at that scale, but you'd build the KV cache, disaggregation and load balancing yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Huawei Ascend 950:&lt;/strong&gt; DeepInfer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most teams with a node or two, the answer is vLLM. DeepInfer is worth following as the reference for how DeepSeek runs its own model, but on a single node it isn't the faster engine.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://warmctl.io/blog/deepseek-b300-vllm-vs-deepinfer/" rel="noopener noreferrer"&gt;warmctl.io&lt;/a&gt;, with the full setup, startup-time breakdown and raw numbers.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>machinelearning</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
