DeepSeek-V4-Flash-Vision-Exp Day 0: 4×H20 Multimodal Deployment and Load Testing¶
On the evening of August 31, 2026, DeepSeek published
DeepSeek-V4-Flash-Vision-Exp on Hugging Face. This is not a renamed text-only DeepSeek-V4 model, but an experimental version of DeepSeek-V4-Flash with a complete vision encoding pipeline added: the repository page marks it as 305B, the checkpoint consists of 48 Safetensors shards totaling approximately 156.31 GiB; the vision side includes a 32-layer ViT, Aligner, image Marker, and image-visibility Attention, with a single image expanding to at most 384 Image Tokens, and native context still at 1,048,576.
After the model was released, I completed deployment, image correctness checks, OpenWebUI hands-on testing, and 79 rounds of multimodal performance testing on Kubernetes using a single node with 4×141GB H20 and the SGLang dedicated Preview Runtime. In the end, all 3,856 requests succeeded with 0 failures; after testing, the Deployment automatically scaled down to 0 and all 4 GPUs were released.
Conclusions first:
- It runs. The raw HF checkpoint loads directly from node NVMe with TP4; SGLang OpenAI-compatible API, single-image, dual-image interleaved, and OpenWebUI image upload all pass.
- Being able to
Readydoes not mean fast startup. NVMe read of the 48 shards took only about 18 seconds, but first-time MHC compilation, DeepGEMM/FlashInfer Autotune, and two sets of CUDA Graph Capture pushed full cold start to 13 minutes 52 seconds. - 720p cold images reached 175.06 Output tok/s at concurrency 16, but P99 TTFT rose to 3.86 seconds. The Warm path with the same image reused reached 332.52 Output tok/s, with P99 TTFT dropping to 1.10 seconds.
- Image count significantly reduces request throughput. 2×720p at C8 was 1.71 req/s; 4×720p at C4 was 2.11 req/s. The two groups have different concurrency, so the latter cannot be used to directly infer that "four images is faster than two."
- This is not an SGLang vs. vLLM A/B. As of 2026-09-01, SGLang provides a Vision-Exp dedicated Preview implementation; vLLM's public DeepSeek Recipe is still the text-only V4, and a text service cannot masquerade as vision support.
References: Model repository, SGLang DeepSeek-V4 Cookbook, vLLM DeepSeek Recipe list.
Model Structure and Runtime Boundaries¶
| Item | Fixed value for this run |
|---|---|
| Model | deepseek-ai/DeepSeek-V4-Flash-Vision-Exp |
| Revision | e46e16bf6035c6f317eb2ac7458eb0362926d402 |
| Outer architecture | DeepseekV4ForCausalLM |
| Repository parameter mark | 305B |
| Context | 1,048,576 |
| Checkpoint | 48 shards, 156.31 GiB |
| Weight format | MoE Experts FP4, remaining Dense/Attention FP8 Mixed |
| Vision module | 32-layer ViT, dim 1024, patch 14, up to 384 Image Tokens/image |
| Speculative decoding | DSpark, gamma=5, verify tokens=6 |
The checkpoint's outer config.json does not use the common standalone vision_config auto-discovery path; the complete vision parameters and reference implementation are located under the repository's inference/ directory. This directly affects model registration, weight loading, and image_url handling in general-purpose serving engines, so the one-line launch command auto-generated on the Hugging Face page cannot replace end-to-end validation.
This run pinned the SGLang Runtime to commit
914197146f8a3407960e5c7037d0463e03c37be9, which is a dedicated Preview Build, not a stable release.
The runtime automatically selected DSV4 Attention, FlashInfer MXFP4 MoE, FlashInfer AllReduce Fusion, and FP8 KV Cache. The logs also warned that the checkpoint does not provide KV Scale, so the runtime fell back to 1.0; therefore, the image correctness Gate cannot be omitted just because throughput testing succeeded.
Experimental Environment¶
| Item | Measured configuration |
|---|---|
| GPU | Single node 4×NVIDIA H20-3e, 143,771 MiB/card, SM90 |
| Driver | 580.126.20 |
| Runtime | SGLang 0.0.0.dev1+g914197146 |
| PyTorch / CUDA | 2.13.0+cu130 / 13.0 |
| Parallelism | TP4, single node |
| Model hot path | Host NVMe, read-only mount into container |
| API | OpenAI-compatible /v1/chat/completions |
| Client | Same vllm bench serve --backend openai-chat |
This is single-node TP4; Tensor Parallel communication does not cross nodes, so RDMA is not used in this round. A node having RDMA devices does not mean a single-node experiment can be written up as "RDMA verified." The H20 is also not in the current Vision-Exp official signed hardware matrix; this article can only prove that this combination of H20, Driver, CUDA, and Preview commit works in practice.
Why Put Weights on NVMe First¶
The shared file system only handles distribution, not the serving hot path. After selecting the node, the full HF checkpoint was copied to local NVMe and verified before startup:
- All 48 index-referenced shards exist and are non-empty;
- Total shard file byte counts match between source and destination directories;
- The destination directory's underlying block device is indeed NVMe;
- Serving is only allowed to start after the write-completion Marker is in place.
This time, copying the 156.31 GiB of weights took 3 minutes 39 seconds. The public example retains only directory semantics and does not expose internal storage addresses:
findmnt -T /srv/model-cache
lsblk -o NAME,TYPE,SIZE,MOUNTPOINTS
rsync -a --partial --info=progress2 \
/shared/models/DeepSeek-V4-Flash-Vision-Exp/v1/ \
/srv/model-cache/DeepSeek-V4-Flash-Vision-Exp/v1/
Kubernetes Launch Method¶
Core parameters are as follows. Image registry, node name, Namespace, and real host directories all use public placeholders:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deepseek-v4-vision-sglang
spec:
replicas: 1
strategy:
type: Recreate
template:
spec:
nodeSelector:
accelerator.example.com/model: h20-141g
containers:
- name: sglang
image: <INTERNAL_SGLANG_VISION_PREVIEW_IMAGE>
command: ["bash", "-lc"]
args:
- |
exec sglang serve \
--model-path /models/DeepSeek-V4-Flash-Vision-Exp/v1 \
--served-model-name DeepSeek-V4-Flash-Vision-Exp \
--trust-remote-code \
--tp 4 \
--speculative-algorithm DSPARK \
--mem-fraction-static 0.85 \
--reasoning-parser deepseek-v4 \
--enable-metrics \
--host 0.0.0.0 \
--port 30000
resources:
requests:
nvidia.com/gpu: "4"
limits:
nvidia.com/gpu: "4"
startupProbe:
httpGet:
path: /v1/models
port: 30000
periodSeconds: 10
failureThreshold: 720
volumeMounts:
- name: model-cache
mountPath: /models
readOnly: true
- name: dshm
mountPath: /dev/shm
volumes:
- name: model-cache
hostPath:
path: <NVME_MODEL_ROOT>
type: Directory
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 64Gi
The Preview Runtime's first-time compilation is very long, so startupProbe must cover the real cold-start window. Allowing up to 120 minutes here is not because normal startup takes two hours, but to prevent Kubelet from killing the pod mid-compilation and restarting from scratch.
Cold Start: NVMe Is Not the Whole Answer¶
| Stage | Duration or timestamp | Observation |
|---|---|---|
| 48-shard NVMe read | ~18 s | Shared storage not on hot path |
| MHC first compilation | 192.8 s | First SM90 kernel generation |
| Main model load complete | ~247 s | 39.50 GB/card |
| DSpark load | 16.4 s | Additional 2.71 GB/card |
| Target CUDA Graph | 36.7 s | 51 batch sizes |
| Draft CUDA Graph | 90.2 s | 51 batch sizes |
| Process start to API Ready | 13 min 52 s | Includes Autotune, JIT, and Graph Capture |
These numbers show: NVMe solves large weight reads, but cannot eliminate runtime first-time compilation and graph capture. If every pod recompiles in an empty cache environment during rolling releases, even a 156 GiB model will struggle to recover in minutes. Before production, compilation cache persistence, pre-compiled artifacts in images, and phased rollout strategies should be further validated.
Functional Correctness and OpenWebUI¶
First, four deterministic Gates were run using the cat and dog images bundled in the Preview image: text-only returns only TEXT_OK, cat image returns only CAT, dog image returns only DOG, and cat-to-dog dual-image interleaved returns only CAT,DOG. All passed; answers change with image substitution, and dual-image order is also correct, so this is not "HTTP 200 but images ignored."
The same OpenAI-compatible API was then connected to OpenWebUI. After uploading a cat image in Light mode, the model correctly identified the cat, pink hooded leather jacket, and sunglasses, completing the loop across cluster access, model discovery, image upload, Chat Template, and multimodal response.

Load Testing Methodology¶
The main test does not evaluate quality with real datasets; instead, it generates deterministic 360p, 720p, 1080p, and multi-image JPEGs specifically to measure serving performance. Cold Cases use a different image per request; Warm Cases reuse the same image. All cases fix output at 64 Tokens, with request-rate=inf, ignore-eos, and Seed fixed; each valid point records three rounds, and the table takes the median metric per round.
vllm bench serve \
--backend openai-chat \
--base-url http://<sglang-service>:30000 \
--endpoint /v1/chat/completions \
--model DeepSeek-V4-Flash-Vision-Exp \
--dataset-name custom_image \
--dataset-path <CASE_JSONL> \
--custom-output-len 64 \
--custom-ensure-client-side-data \
--enable-multimodal-chat \
--request-rate inf \
--ignore-eos \
--disable-shuffle \
--save-result --save-detailed
Although the client command name is vllm bench serve, the service under test is still SGLang. It only sends requests through the OpenAI-compatible HTTP interface; a unified client facilitates future framework A/B testing. SGLang's built-in Benchmark Client can be used for engine-internal diagnostics, but numbers from two different clients cannot be directly combined into a fair comparison.
This round generated 79 result JSONs total: 112 warm-up requests and 3,744 official requests, for a combined 3,856 successes, 0 failures. The full matrix took 46 minutes.
Performance Results¶
Single-Image Cold and Warm¶
| Case | Concurrency | Req/s | Output tok/s | P50 TTFT | P99 TTFT | P50 TPOT |
|---|---|---|---|---|---|---|
| 360p Cold | 1 | 1.55 | 99.43 | 225.15 ms | 230.09 ms | 6.57 ms |
| 360p Cold | 4 | 2.71 | 173.19 | 236.48 ms | 516.07 ms | 18.94 ms |
| 360p Cold | 8 | 3.46 | 221.40 | 426.19 ms | 718.60 ms | 31.05 ms |
| 360p Cold | 16 | 4.34 | 277.66 | 463.62 ms | 1,243.54 ms | 47.91 ms |
| 360p Warm | 1 | 1.59 | 101.87 | 189.28 ms | 195.55 ms | 7.00 ms |
| 360p Warm | 4 | 3.01 | 192.90 | 201.70 ms | 371.30 ms | 17.44 ms |
| 360p Warm | 8 | 3.87 | 247.44 | 214.16 ms | 524.96 ms | 28.42 ms |
| 360p Warm | 16 | 5.30 | 339.17 | 376.11 ms | 674.81 ms | 40.92 ms |
| 720p Cold | 1 | 1.25 | 80.09 | 378.21 ms | 386.84 ms | 6.58 ms |
| 720p Cold | 4 | 1.98 | 126.96 | 401.66 ms | 1,072.97 ms | 24.14 ms |
| 720p Cold | 8 | 2.35 | 150.34 | 731.92 ms | 1,963.41 ms | 42.18 ms |
| 720p Cold | 16 | 2.74 | 175.06 | 932.64 ms | 3,861.24 ms | 69.06 ms |
| 720p Warm | 1 | 1.66 | 106.09 | 209.24 ms | 214.50 ms | 6.38 ms |
| 720p Warm | 4 | 3.10 | 198.70 | 236.05 ms | 399.69 ms | 15.38 ms |
| 720p Warm | 8 | 4.06 | 259.62 | 368.13 ms | 624.84 ms | 24.81 ms |
| 720p Warm | 16 | 5.20 | 332.52 | 426.87 ms | 1,103.43 ms | 40.17 ms |
For 720p at C16, the Warm path relative to Cold: both request throughput and output throughput improve by about 90%, P50 TTFT drops 54.2%, and P99 TTFT drops 71.4%. This is not "the model itself suddenly became twice as fast," but rather that same-image reuse reduces repeated vision preprocessing and Encoder work. If real business traffic has mostly unique images, the Cold table should be used as the capacity baseline.
High Resolution and Multi-Image¶
| Case | Concurrency | Req/s | Output tok/s | P50 TTFT | P99 TTFT | P50 TPOT |
|---|---|---|---|---|---|---|
| 1080p Cold | 1 | 1.28 | 82.04 | 399.35 ms | 404.21 ms | 6.17 ms |
| 1080p Cold | 4 | 2.11 | 134.74 | 753.29 ms | 1,090.56 ms | 16.94 ms |
| 1080p Cold | 8 | 2.54 | 162.38 | 912.25 ms | 1,992.23 ms | 33.05 ms |
| 2×720p Cold | 1 | 1.03 | 66.22 | 571.68 ms | 580.31 ms | 6.45 ms |
| 2×720p Cold | 4 | 1.50 | 96.02 | 1,035.90 ms | 1,926.30 ms | 26.43 ms |
| 2×720p Cold | 8 | 1.71 | 109.42 | 1,431.42 ms | 3,678.51 ms | 51.90 ms |
| 4×720p Cold | 1 | 0.74 | 47.44 | 990.36 ms | 1,000.40 ms | 5.56 ms |
| 4×720p Cold | 4 | 2.11 | 134.75 | 800.79 ms | 1,192.45 ms | 16.07 ms |
For multi-image scenarios, you should look at Req/s, TTFT, and image count together, not just Token/s. 4×720p at C4 processes about 8.44 images per second, but each request itself contains four images; its scheduling pressure differs from 2×720p at C8, so you cannot rank horizontally by Req/s alone.
First-time new-shape JIT must be recorded separately¶
The first officially recorded P99 TTFT for 360p at C16 was 7.91 seconds, and the following two rounds dropped to about 1.22–1.24 seconds. All raw JSON was retained; the main table follows the pre-defined rule of taking the median of three rounds, which is 1.24 seconds, without deleting the first round. For the Preview Runtime, after /v1/models is Ready, there may still be first-time compilation for new Batch Shapes, so Canary warm-up needs to cover the resolutions, image counts, and concurrency planned for production use, not just send a single text request.
OpenWebUI integration¶
OpenWebUI only needs an OpenAI-compatible Base URL that is reachable from its own network:
Before integration, verify /v1/models and one /v1/chat/completions carrying a Data URL from the network where the OpenWebUI Pod resides. If the model appears in the selector but there is no image upload button, you also need to explicitly mark Vision in OpenWebUI's model capability settings; in this version, image upload can be completed directly from the returned model, without needing a frontend plugin.
In cross-cluster scenarios, do not write temporary Pod IPs into OpenWebUI. You can use a fixed Ingress, Gateway API, or create a Selectorless Service + EndpointSlice in the OpenWebUI cluster pointing to a stable entry point. Public configurations should remove real internal network addresses.
Why there is no vLLM data¶
As of 2026-09-01, the DeepSeek-V4-Flash listed on the vLLM Recipe page is a text model, and there is no Vision-Exp under the Multimodal category either. The text V4 being able to load language weights from the same family does not mean it can load ViT/Aligner, process image_url, maintain image visibility masks, and correctly return visual answers.
Therefore, this article does not do the following two things:
- It does not use the text-only vLLM image to run "image requests" and then write the errors off as poor vLLM performance;
- It does not let images be silently ignored and then fake an SGLang/vLLM A/B comparison just because of an HTTP 200.
Once vLLM has explicit model registration, a dedicated Recipe, and image E2E tests, the same client, the same JSONL, the same H20 node, and the same NVMe Checkpoint from this article can be reused for a fair retest.
Production recommendations¶
- Pin the Preview commit and image Digest. Do not use a drifting
latest. - CFS is only the source; NVMe is the hot path. Verify the Block Device and complete Marker before startup.
- Reserve at least 15 minutes of cold-start budget. Also persist the compilation/Autotune Cache and verify whether it can shorten the second startup.
- Apply Admission Control by image count and resolution. The same text token count does not mean four-image requests have the same cost.
- Build capacity baselines separately for Cold/Warm. Do not cite Warm results when business images are unique.
- Keep the first-time new-shape tail latency. Canary warm-up covers real concurrency; do not delete the "ugly" first round.
- Separate quality from performance. The cat-and-dog Gate in this article proves the image pipeline works, but it cannot replace quality evaluations such as MMMU, MathVista, RealWorldQA, and OCRBench.
- Automatically release GPUs when the task ends. This time, a least-privilege cleanup Job scaled the Deployment to 0 after the Benchmark
Completeand confirmed the Serving Pod exited.
What this article did not prove¶
- Did not verify the model's claimed 1M Context with images as joint input;
- Did not run standard vision quality datasets, so no model capability ranking can be given;
- Did not verify cross-node TP/EP, RDMA, or P/D separation;
- Did not obtain vLLM Vision-Exp data, so no framework winner can be declared;
- Preview Runtime, FP8 KV Scale fallback, and H20 non-officially-signed hardware remain launch risks.
But the most critical Day 0 engineering question has been answered: DeepSeek-V4-Flash-Vision-Exp can provide real multimodal service on 4×141GB H20 via SGLang Preview with TP4; the NVMe weight hot path, OpenWebUI image pipeline, and the 3,856-request performance matrix are all closed-loop, and the GPUs were automatically released after the test ended.