Edit: Now I think about it, this might be the cheapest way to run the DeepSeek V4 Flash 0731 on a dedicated inference server at original weights. I havenβt run mixed load benchmarks but I guess itβs possible to generate $3-$4 worth of tokens per hour and still maintain a usable per-user throughput.
Otherwise, you can probably buy one of these second hand from somewhere (SXM A100s are available that way) and run it in an adapter board.
I found an offer to rent two at $1.65 per hour https://spark.enverge.ai/#pricing
The MI300X will vastly outperform it for only a slightly higher price.
The only solution is more companies making high end units, only competition will make it better for consumers.
You shouldn't rent one out if you're just serving it for yourself, but from a financial standpoint if you sell to users you can take a 100% margin.
we did some work on this for 2xMi300x (kindly referenced in the readme) https://blog.doubleword.ai/deepseek-v4-flash-mi300x. https://hotaisle.xyz/quick-start hotaisle is great for getting Mi300x to experiment with
Serving local models has advantages other than price. If you work in restricted industries, or have a strong need to protect your IP, or if you just value privacy more than cost, you now have options.
This is not the real margins, even if you are selling to 8 users it's 90 tps per median stream. So assuming that .6-.7$
This is not even remotely worth it.
You need to 3x this tps(~1500 tps) to be worth it, and that's what most providers are doing, at 20-30 users at 50-60 tps with better optimized batch processing and kernels you can make some profit.
Lets assume that you've got 2 million input tokens, 1 million output tokens and 98.5 million cached tokens to process. That would cost 2 * $0.14 + 1 * $0.28 + 98.5 * $0.0028 = $0.8358 with DeepSeek API pricing.
For comparison, it would take 2M / 8000 + 1M / 800 = 1500 seconds to process this amount of tokens with the linked framework, which is about $0.83 when we assume $2/hr for one MI300X.
However, other inference providers have 10 times higher prices for cached tokens, which results in a comfortable margin.
And we should not discount that DeepSeek also gets paid in data, which is probably more valuable to them.
And I believe that this framework still has some room for optimization for generation with high batch sizes.
Dumbed down quantization?
No. Full intended inference weights preserved, so far so good.
Slow performance?
No again. Looks like you could get over 150 tokens/second.
Give up context window size?
Yes. Original model is trained for and served at 1M, this is 256k. A very practical tradeoff though. Codex is in this range, and quality does start to drop off toward the full size.
Based on your $0.83 estimate, the margin isn't great. This is within shooting distance of "at cost" which is probably pretty close to what DeepSeek is operating with, ignoring the value of the data they're collecting of course.
> And I believe that this framework still has some room for optimization for generation with high batch sizes.
If that optimization can bring this scenario closer to $0.50 then it gets pretty compelling, otherwise I'm not confident.
I can tell you it will pop in 10 years and when it pops, it will still be 20x bigger than in 2026. Does that even make any sense?
People said AI bubble will pop soon in 2024 and that it was overvalued. Turns out, many AI stocks 10x, 20x since 2024. Actual usage has gone exponential as well. Anthropic revenue went from $100m ARR at start of 2024 to $80b ARR today.
Debt-backed investors have to pay up eventually. =3
Well, given the literal trillions being spent, the only ways this pays off are:
1. AI replaces a non-trivial fraction of human employees.
2. Someone builds a Culture Mind, and humans become (hopefully) pampered pets of AIs we don't understand. Seems unlikely, but it would arguably count as a payoff even if it made money meaningless.
Or maybe the AIs don't want pets, and you get SkyNet. Which definitely doesn't care about paying off anyone's investments.
When you look at various news articles about investors, yeah, there are definitely a lot of rich people who think that they're going to automate all human labor or just bring about the Singularity. Possibly with them in charge of the rest of us. If you don't make these kinds of wild assumptions, then yeah, this is looking like one of the biggest bubbles ever.
This repository contains the configuration and patches I use to run deepseek-ai/DeepSeek-V4-Flash-0731 on one AMD MI300X in production. It includes the Docker Compose stack, SHA-256-pinned file overlays, reference diffs against upstream, and tuning tables. The checkpoint runs as shipped, without additional weight quantization or offload.
Results from the pinned stack (vLLM ROCm nightly 0.26.1rc1.dev229+g124154a88.rocm723, AITER 0.1.19):
| Metric | Result |
|---|---|
| Single-stream decode (median per-stream, DSpark-7) | 168.6 tok/s |
| Prefill with tuned kernels | β 7.9β8.5K tok/s (6,988β7,019 tok/s on fresh prompts in the shipping profile) |
| 8 concurrent streams | 542 tok/s aggregate, 90.3 tok/s median per stream |
| 64-stream burst | 830 tok/s aggregate, no OOM, no engine errors |
| Context | 256K validated (the architecture supports 1M) |
| Weights in HBM | 156.67 GiB β no additional quantization or weight offload |
The official vLLM recipe targets NVIDIA and newer AMD hardware. Running the model reliably on MI300X required fixes for its FP8 format, MoE routing at high concurrency, causal speculative verification, CPU-KV synchronization, and several untuned kernel shapes. This repository collects those fixes and pins the versions used in production.
The MI300X has 192 GB of HBM3 and 5.3 TB/s of memory bandwidth, with 2.4Γ the HBM capacity of an H100 SXM5 (AMD). Doubleword's write-up estimates that it costs roughly half as much at list price. For this 304B-parameter checkpoint, the memory capacity allows a simple single-GPU deployment:
MI300X (CDNA3) implements the AMD/Graphcore fnuz variant of E4M3, while MI325X and newer use OCP-standard FP8 (background). A kernel that assumes OCP semantics on MI300X can be wrong by a factor of two in the scale domain. Correctness on this FP8 implementation was the first priority; performance tuning came afterward.
Fergus Finn's MI300X worklog and the accompanying Doubleword repository identified the FP8 incompatibility, missing AITER fast paths on gfx942, HIP-graph hazards in sparse MLA decode, and MoE routing bugs. The official vLLM recipe covers NVIDIA hardware and newer AMD GPUs (MI325X at 4K context and MI355X), but not a single-MI300X production configuration for the 0731 checkpoint.
This repository adds:
gfx942 shapes the packaged tables were missing, plus a gfx942 OGS geometry override for the MXFP4 experts.fp8_ds_mla GPU cache + 96 GiB native CPU offload, with a load-path fencing fix that upstream issue #47282 documents but PR #47291 never merged..
βββ compose.yaml # The production stack (vLLM ROCm + Caddy), digest-pinned
βββ Caddyfile.example # Copy to Caddyfile; set hostname, email, and source CIDR
βββ vllm-entrypoint.sh # Removes stale CPU-KV mmaps from /dev/shm before start
βββ SHA256SUMS # SHA-256 pins for every runtime artifact
βββ patches/
β βββ *.py # Byte-for-byte production overlays (mounted read-only)
β βββ diffs/*.patch # Unified diffs vs. the upstream base revision
β βββ README.md # Provenance and regeneration instructions
βββ tuning/
βββ *.csv # AITER A8W8 blockscale tuning tables for gfx942
The stack uses a digest-pinned official vLLM ROCm nightly with:
--trust-remote-code and the DeepSeek V4 tokenizer, reasoning, and tool parsersfp8_ds_mla KV cache (UE8M0 block-scaled FP8, not generic unscaled FP8) with 256-token blocksVLLM_ROCM_USE_AITER=1 and --moe-backend triton; Triton OGS handles the grouped MXFP4 experts, while AITER handles attention and dense linear layersOne MI300X (gfx942, 304 CUs, ~192 GiB HBM), a working AMD kernel driver, recent Docker Compose, ~235 GiB RAM for the CPU KV tier, and ~500 GB disk (the model cache alone is ~156 GB).
VLLM_IMAGE='vllm/vllm-openai-rocm@sha256:e68d18b2ba50298661bfc49baf01158fbf036645c2362cccf3e8a7a79fe6c69a'
MODEL='deepseek-ai/DeepSeek-V4-Flash-0731'
REVISION='7872f01b1d1fe23eabc4c98b48bffcef5a386062'
docker pull "$VLLM_IMAGE"
docker run --rm --entrypoint hf \
-v /root/.cache/huggingface:/root/.cache/huggingface \
"$VLLM_IMAGE" download "$MODEL" --revision "$REVISION"
cp Caddyfile.example Caddyfile # then set your hostname, email, and remote_ip CIDR
mkdir -p aiter-cache crash-dumps
chmod +x vllm-entrypoint.sh
sha256sum -c SHA256SUMS # verify the overlays before first start
docker compose config -q
docker compose up -d
docker compose logs -f inference
A healthy start takes ~5 minutes and must show all of:
Model loading took 156.67 GiB
DSpark draft model loaded: 96 params
GPU KV cache size: 1,927,444 tokens
Maximum concurrency for 262,144 tokens per request: 7.35x
Created mmap file /dev/shm/vllm_offload_...mmap (103.08 GB)
Capturing CUDA graphs (FULL)
Application startup complete
After graph capture, run rocm-smi --showmeminfo vram. The warmed high-water mark is ~204.5 GB of 205.8 GB. If only a few hundred MB remain, the server may start but fail on the first request.
HOST='your-host.example.com'
curl -fsS "https://$HOST/v1/models"
curl -sS "https://$HOST/v1/completions" \
-H 'Content-Type: application/json' \
-d "{\"model\": \"deepseek-ai/DeepSeek-V4-Flash-0731\",
\"prompt\": \"Calculate 17 * 23. Answer with the number only.\",
\"temperature\": 0, \"max_tokens\": 32}"
Each patches/*.py file is a full-file overlay mounted read-only over its counterpart in the container; compose.yaml contains the target paths. The corresponding diffs/*.patch records the change from its upstream base. The base image remains digest-pinned, so upgrades require changing the image reference and revalidating the stack.
| Overlay | Mounted over | Fixes | Needed when |
|---|---|---|---|
gpt_oss_triton_kernels_moe.pack128-fused-silu-fast-routing.py |
vllm/.../fused_moe/experts/gpt_oss_triton_kernels_moe.py |
MXFP4 bitmatrix padding lanes + fused-SiLU grouped experts + fast DeepSeek routing | Required for the MXFP4 Triton path; the mask fix is not yet upstream |
mxfp4.fused-silu.py |
vllm/.../fused_moe/oracle/mxfp4.py |
Gate/up interleave layout for the fused-SiLU kernel | Required with the fused-SiLU overlay; skip both if you keep the standard SiLU path |
triton-kernels-matmul-ogs-opt-flags.dsv4-mi300x.py |
vllm/third_party/triton_kernels/matmul_ogs_details/opt_flags.py |
gfx942 MXFP4 OGS tile geometry (up to 1,536 routed rows) |
Performance on gfx942; the stock geometry slows sharply above 768 routed rows |
fused_compress_quant_cache.fnuz-shuffle.py |
vllm/models/deepseek_v4/common/ops/fused_compress_quant_cache.py |
FNUZ FP8 + 16Γ16 preshuffle in the Lightning Indexer cache writer | Required on MI300X; MI325X/MI355X use OCP FP8 and must keep the stock bytes |
aiter_pa_mqa_logits.i64.py |
aiter/ops/triton/gluon/pa_mqa_logits.py |
64-bit offsets in the ChunkK=256 paged-MQA kernels |
Required when KV offsets can exceed 4 GiB; skip for small KV pools |
rocm_aiter_mla_sparse.prefill-bh64.py |
vllm/v1/attention/ops/rocm_aiter_mla_sparse.py |
Deterministic torch.topk prefill + BLOCK_H=64 head-512 sparse prefill |
Determinism is required for reproducible tool calls; BLOCK_H=64 is performance |
rocm_aiter_mla.dspark-causal.py |
vllm/v1/attention/backends/mla/rocm_aiter_mla.py |
Causal multi-token speculative verification | Required for DSpark on ROCm small-head MLA β now upstream; the overlay is the upstream file verbatim |
dspark-speculator.independent-draft-gumbel.py + spec-decode-utils.independent-draft-gumbel.py |
vllm/v1/worker/gpu/spec_decode/dspark/speculator.py + .../spec_decode/utils.py |
Draft-proposal Gumbel noise salted away from rejection/recovery noise | Required only with draft_sample_method=probabilistic (the recipe's greedy path does not need it) |
kv_offload_cpu_gpu_worker.load-war.py |
vllm/v1/kv_offload/cpu/gpu_worker.py |
Fence CPUβGPU KV restores behind in-flight compute (#47282, PR #47291) | Required only with --kv-offloading-backend native |
MXFP4 routing. The MoE bitmatrix kernel pads its block columns to a Triton block size, but the padding lanes were masked against the global tensor bound instead of the logical block size. Under load, padded lanes corrupted the routing matrix, causing near-match tool names and forgotten schemas on long prompts. The one-line fix is mask = (offs_local < BLOCK_SIZE) & (offs_global < nonzero_indx_size), taken from Doubleword commit c32932bb9. The overlay also includes fused-SiLU and fast-routing changes for grouped MXFP4 experts.
FP8 format. DeepSeek V4's Lightning Indexer cache uses FP8. The stock writer emits OCP E4M3 bytes in row-major order, while AITER on MI300X consumes AMD FNUZ E4M3 bytes in a preshuffled 16Γ16 tile layout. In the worst case, interpreting one format as the other produces a factor-of-two scale error. The overlay selects float8e4b8 with FP8_MAX=224.0 and shuffled write offsets on ROCm, while leaving the OCP path unchanged elsewhere.
This stack uses probabilistic drafting with block rejection. The two Gumbel overlays keep draft-proposal noise independent of rejection and recovery noise.
Key optimizations in the production configuration:
| Change | Effect |
|---|---|
Tune 21 recurring A8W8 GEMM shapes for 304-CU gfx942 |
+42β62% single/double-stream decode; +10β35% at 8β64 streams |
| Fused SiLU, fast DeepSeek routing, batch-sensitive expert tiles | Native C1 decode 34.5 β 56.6 tok/s (+64%); routing kernel 42.6 β 11.9 Β΅s/layer |
BLOCK_H=64 sparse-prefill tile |
Prefill reaches 7.9β8.5K tok/s; sparse-attention trace 317 β 142 ms per request |
| Static K=7, probabilistic + block rejection, causal verify | 119.5 tok/s single-stream with correct output |
| 2,048-token budget + 1,024-token long-prefill cap | Late short-request TTFT behind a 52K prefill: 8.2 s β 0.5 s |
| 20 GB GPU KV + 96 GiB CPU tier | 1.93M-token length-equivalent capacity; seven 256K requests admitted |
Distinct ~400-word prompts, streaming, temperature=1.0, top_p=0.95; C1βC8 at 512 output tokens, C64 at 256:
| Streams | Aggregate tok/s | Median per-stream decode | TTFT p50 |
|---|---|---|---|
| 1 | 126.2 | 168.6 tok/s | 1.026 s |
| 2 | 145.4 | 152.7 | 0.939 s |
| 4 | 316.8 | 108.6 | 0.369 s |
| 8 | 542.3 | 90.3 | 1.027 s |
| 64 | 830.2 | 16.4 | 2.190 s |
DSpark acceptance is prompt-dependent; treat these as gates for this exact image, not universal model benchmarks.
With the tuned kernels, uncached prefill reaches 7.9β8.5K tok/s, depending on scheduler budget: 7.90β7.99K at C1 with an 8,192-token budget and 8.46β8.51K at C4. The production profile uses a 2,048-token budget for latency isolation, giving 6,988β7,019 tok/s on fresh prompts. With the 1,024-token long-prefill cap, an 8.9K-token prompt reaches 5.20β5.29K tok/s at C1. In exchange, TTFT for a short request queued behind a 52K cold prefill drops from 8.2 s to 0.5 s. Warm recall of 380K cached tokens takes 0.64β2.65 s after a 120β125 s cold prefill.
HSA_STATUS_ERROR_OUT_OF_RESOURCES. Do not raise --kv-cache-memory-bytes; monitor HBM usage for growth.--kv-offloading-size 96 --kv-offloading-backend native maps ~103 GB in /dev/shm for evicted prefix-cache entries. The entrypoint removes stale mappings after crashes.The stack, documentation, and vLLM-derived overlays are Apache-2.0 (see LICENSE); the AITER-derived overlay keeps its MIT header. Upstream base revisions for every diff are recorded in patches/README.md. The model itself is MIT-licensed.
All links verified 2026-08-04.
temperature=1.0, top_p=0.95; MIT licensenum_speculative_tokens=7), FP8 KV, block size 256, deepseek_v4 parsers; AMD guidance for MI325X/MI355Xgfx942, HIP-graph hazards, routing bugsc32932bb9 ("mask MXFP4 bitmatrix padding lanes by logical block size")77469c9 β "[ROCm][MLA] Mask the AITER MLA small-head verify flatten causally (#50476)"vllm/vllm-openai-rocm)Was also surprised to learn just how much of Codex's window was being burnt on shit I didn't want or use. Sure I can pass this and that flag to eliminate most of it, but for a $200/mo product aimed at professionals, that isn't something anyone should have to janitor (also totally ignoring the bandaid of banked resets they've slapped over their repeated mistakes).
It's wild just how far $20 will get you with Deepseek, even at their new rates. Buyers Remorse is my very least favorite feeling, I felt sick thinking about what the $1200 I had given OAI this year would have gotten me had I only tried sooner.