在单颗 AMD MI300X 上运行 DeepSeek V4 Flash
一个开源仓库提供了在单颗 AMD MI300X 上生产运行 DeepSeek-V4-Flash-0731 的完整配置与补丁,无需额外量化或权重卸载。该 304B 参数模型在 192 GB HBM 上实现单流 168.6 tok/s 解码、8 并发流 542 tok/s 聚合吞吐,并验证了 256K 上下文。
为 MI300X 提供了可部署的生产栈,包含 FP8 格式修复、推测解码优化和混合 KV 缓存策略,单卡就能服务 256K 上下文。
在单块 AMD MI300X 上运行 DeepSeek V4 Flash
本仓库包含我用于运行以下内容的配置和补丁deepseek-ai/DeepSeek-V4-Flash-0731在一块 AMD MI300X生产环境中的配置和补丁。其中包括 Docker Compose 栈、以 SHA-256 固定校验的文件覆盖层、与上游的参考差异对比,以及调优参数表。该 checkpoint 按发布原样运行,未做额外的权重量化或卸载。
固定技术栈(vLLM ROCm nightly 0.26.1rc1.dev229+g124154a88.rocm723、AITER 0.1.19)的结果:
| 指标 | 结果 |
|---|---|
| 单流解码(每流中位数,DSpark-7) | 168.6 tok/s |
| 使用调优内核进行 Prefill | ≈ 7.9–8.5K tok/s(在发布配置下,全新提示词上为 6,988–7,019 tok/s) |
| 8 路并发流 | 聚合 542 tok/s,每路流中位数 90.3 tok/s |
| 64 路流突发 | 聚合 830 tok/s,无 OOM,无引擎错误 |
| 上下文 | 256K 已验证(该架构支持 1M) |
| 权重存放于 HBM | 156.67 GiB —— 无额外量化或权重卸载 |
官方 vLLM 方案面向 NVIDIA 及较新的 AMD 硬件。要在 MI300X 上稳定运行该模型,需要针对其 FP8 格式、高并发下的 MoE 路由、因果投机验证、CPU-KV 同步以及若干未调优的 kernel 形状进行修复。本仓库汇集了这些修复,并锁定了生产环境中所使用的版本。
为什么选择 MI300X
MI300X 拥有 192 GB 的 HBM3 和 5.3 TB/s 的内存带宽,其 HBM 容量是 H100 SXM5 的 2.4 倍(AMD)。Doubleword 的分析估计,其标价大约只有后者的一半。对于这个 304B 参数的 checkpoint,这样的内存容量使得简单的单 GPU 部署成为可能:
- 整个模型可完全放入 HBM,无需 PCIe 权重流式传输或层卸载。
- 还有空间容纳一个 20 GB 的 GPU KV 池,以及一个 96 GiB 的 CPU 层级,用于存放被逐出的前缀缓存条目。
- 单张卡可处理 2–8 路典型并发流,并可突发支持多达 64 路流。
MI300X(CDNA3)实现的是 AMD/Graphcore fnuz 变体的 E4M3,而 MI325X 及更新型号使用 OCP 标准的 FP8(背景)。在 MI300X 上假设采用 OCP 语义的 kernel 在 scale 域上可能偏差两倍。在这个 FP8 实现上,正确性是第一优先级;性能调优随后进行。
已有工作,以及本仓库新增的内容
Fergus Finn 的 MI300X 工作日志以及配套的 Doubleword 仓库识别出了 FP8 不兼容、gfx942 上缺失的 AITER 快速路径、稀疏 MLA 解码中的 HIP-graph 隐患,以及 MoE 路由 bug。官方 vLLM recipe覆盖了 NVIDIA 硬件和较新的 AMD GPU(4K 上下文下的 MI325X 以及 MI355X),但没有覆盖针对 0731 checkpoint 的单 MI300X 生产配置。
本仓库新增了:
- 针对固定版本 ROCm nightly 的正确性 overlay,包括尚未进入上游 vLLM 的修复。
- 一套经过验证的服务配置,采用概率性 DSpark 草稿、块拒绝和静态 K=7。它使用 2,048 token 的调度器预算和 1,024 token 的长 prefill 上限,以防止冷启动提示词阻塞其他流。
- AITER GEMM 调优表,针对打包表中缺失的重复出现的
gfx942形状,外加针对 MXFP4 专家的gfx942OGS 几何覆盖。 - 混合 KV 策略:20 GB 的
fp8_ds_mlaGPU 缓存 + 96 GiB 原生 CPU 卸载,并附带一个加载路径围栏修复,上游 issue #47282 有文档记录,但 PR #47291 从未合并。
仓库结构
.
├── 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
运行时配置
该技术栈使用摘要固定的官方 vLLM ROCm nightly 版本,包含:
--trust-remote-code以及 DeepSeek V4 tokenizer、推理和工具解析器fp8_ds_mlaKV 缓存(UE8M0 块缩放 FP8,而非通用的非缩放 FP8),使用 256-token 块VLLM_ROCM_USE_AITER=1和--moe-backend triton;Triton OGS 处理分组 MXFP4 专家,而 AITER 处理注意力和稠密线性层- DSpark-7 投机解码,采用概率性草稿和块拒绝
- 完整/可断 CUDA graph 捕获,在稳定解码期间每个 token 只需一次 graph 启动
- Caddy 作为 IP 白名单 HTTPS 代理
部署它
1. 主机前提条件
一块 MI300X(gfx942,304 个 CU,约 192 GiB HBM)、一个可正常工作的 AMD 内核驱动、较新的 Docker Compose、用于 CPU KV 层约 235 GiB 内存,以及约 500 GB 磁盘(仅模型缓存就约 156 GB)。
2. 拉取固定版本的运行时和模型
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"
3. 准备文件
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
4. 启动
docker compose config -q
docker compose up -d
docker compose logs -f inference
一次健康的启动大约需要 5 分钟,并且必须显示以下全部内容:
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
图捕获完成后,运行 rocm-smi --showmeminfo vram。预热后的高水位线约为 205.8 GB 中的 204.5 GB。如果只剩几百 MB,服务器可能能启动,但会在第一个请求时失败。
5. 冒烟测试
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}"
补丁
每个 patches/*.py 文件都是一个整文件覆盖层,以只读方式挂载到容器中对应的文件之上;compose.yaml 包含目标路径。对应的 diffs/*.patch 记录了相对于其上游基线的变更。基础镜像仍然以摘要固定,因此升级需要更改镜像引用并重新验证整个技术栈。
| 覆盖层 | 挂载于 | 修复 | 需要时 |
|---|---|---|---|
gpt_oss_triton_kernels_moe.pack128-fused-silu-fast-routing.py | vllm/.../fused_moe/experts/gpt_oss_triton_kernels_moe.py | MXFP4 bitmatrix 填充通道 + 融合 SiLU 分组专家 + 快速 DeepSeek 路由 | MXFP4 Triton 路径必需;掩码修复尚未上游合并 |
mxfp4.fused-silu.py | vllm/.../fused_moe/oracle/mxfp4.py | 融合 SiLU 内核的 Gate/up 交错布局 | 与融合 SiLU 叠加层配合使用;如果保留标准 SiLU 路径,则两者均可跳过 |
triton-kernels-matmul-ogs-opt-flags.dsv4-mi300x.py | vllm/third_party/triton_kernels/matmul_ogs_details/opt_flags.py | gfx942 MXFP4 OGS tile 几何配置(最多 1,536 路由行) | 性能在 gfx942 上;默认几何配置在超过 768 路由行后急剧变慢 |
fused_compress_quant_cache.fnuz-shuffle.py | vllm/models/deepseek_v4/common/ops/fused_compress_quant_cache.py | FNUZ FP8 + 16×16 预混洗,用于 Lightning Indexer 缓存写入器 | MI300X 上必需;MI325X/MI355X 使用 OCP FP8,必须保留原始字节 |
aiter_pa_mqa_logits.i64.py | aiter/ops/triton/gluon/pa_mqa_logits.py | ChunkK=256 分页 MQA 内核中的 64 位偏移量 | 当 KV 偏移量可能超过 4 GiB 时必需;小型 KV 池可跳过 |
rocm_aiter_mla_sparse.prefill-bh64.py | vllm/v1/attention/ops/rocm_aiter_mla_sparse.py | 确定性 torch.topk 预填充 + BLOCK_H=64 head-512 稀疏预填充 | 可复现的工具调用需要确定性;BLOCK_H=64 关乎性能 |
rocm_aiter_mla.dspark-causal.py | vllm/v1/attention/backends/mla/rocm_aiter_mla.py | 因果多 token 投机验证 | ROCm 上 DSpark small-head MLA 所需——现已上游;overlay 就是上游文件的原样副本 |
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 | 草拟提案:将 Gumbel 噪声与拒绝/恢复噪声分离 | 仅在 draft_sample_method=probabilistic 时需要(该配方的贪心路径不需要它) |
kv_offload_cpu_gpu_worker.load-war.py | vllm/v1/kv_offload/cpu/gpu_worker.py | 将 CPU→GPU 的 KV 恢复挡在正在进行的计算之后(#47282,PR #47291) | 仅在 --kv-offloading-backend native 时需要 |
两个重要的正确性修复
MXFP4 路由。 MoE bitmatrix 内核会将其块列填充到 Triton 块大小,但填充通道却是针对全局张量边界进行掩码,而非逻辑块大小。在高负载下,填充通道会破坏路由矩阵,导致长提示词下出现近似匹配的工具名称和被遗忘的 schema。一行修复方案是 mask = (offs_local < BLOCK_SIZE) & (offs_global < nonzero_indx_size),取自 Doubleword 提交 c32932bb9。该 overlay 还包含针对分组 MXFP4 专家的 fused-SiLU 和快速路由改动。
FP8 格式。 DeepSeek V4 的 Lightning Indexer 缓存使用 FP8。原版写入器以行主序输出 OCP E4M3 字节,而 MI300X 上的 AITER 则以预混洗的 16×16 tile 布局消费 AMD FNUZ E4M3 字节。在最坏情况下,将一种格式误读为另一种会产生两倍的缩放误差。该 overlay 在 ROCm 上选择 float8e4b8 配合 FP8_MAX=224.0 以及混洗写入偏移,而在其他地方保持 OCP 路径不变。
投机解码
该技术栈采用带块拒绝的概率性起草。两个 Gumbel overlay 使起草提议噪声与拒绝和恢复噪声保持独立。
性能
生产配置中的关键优化:
| 改动 | 效果 |
|---|---|
为 304-CU 调优 21 种重复出现的 A8W8 GEMM 形状 gfx942 | 单流/双流解码提升 42–62%;在 8–64 并发流下提升 10–35% |
| 融合 SiLU、快速 DeepSeek 路由、对批次敏感的专家分块 | 原生 C1 解码从 34.5 → 56.6 tok/s(+64%);路由 kernel 从 42.6 → 11.9 µs/层 |
BLOCK_H=64 稀疏预填充分块 | 预填充达到 7.9–8.5K tok/s;稀疏注意力追踪从 317 → 142 ms/请求 |
| 静态 K=7,概率 + 块拒绝,因果验证 | 单流 119.5 tok/s,且输出正确 |
| 2,048-token 预算 + 1,024-token 长预填充上限 | 52K 预填充之后的迟到短请求 TTFT:8.2 s → 0.5 s |
| 20 GB GPU KV + 96 GiB CPU 层级 | 1.93M-token 长度等效容量;可接纳七个 256K 请求 |
最终并发扫描
各不相同的约 400 词提示词,流式,temperature=1.0, top_p=0.95;C1–C8 为 512 输出 token,C64 为 256:
| 流 | 聚合 tok/s | 每流解码中位数 | 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 的接受率取决于提示词;请将这些视为针对这张具体图像的阈值,而非通用的模型基准。
预填充
使用调优后的内核,未命中缓存的预填充可达到 7.9–8.5K tok/s,具体取决于调度器预算:在 C1 下、预算为 8,192 token 时为 7.90–7.99K,在 C4 下为 8.46–8.51K。生产配置使用 2,048 token 的预算以实现延迟隔离,在全新提示词上可达到 6,988–7,019 tok/s。在 1,024 token 的长预填充上限下,一个 8.9K token 的提示词在 C1 下可达到 5.20–5.29K tok/s。作为交换,一个排在 52K 冷预填充之后的短请求,其 TTFT 从 8.2 s 降至 0.5 s。在 120–125 s 的冷预填充之后,对 380K 缓存 token 的热召回耗时 0.64–2.65 s。
生产注意事项
- HBM 余量有限。预热后的高水位为 205.8 GB 中的 204.5 GB。一个 30 GB 的 KV 池可以加载,但在图捕获期间会因
HSA_STATUS_ERROR_OUT_OF_RESOURCES而失败。不要提高--kv-cache-memory-bytes;请监控 HBM 使用量的增长。 - CPU KV 层存储的是缓存条目,而非权重。
--kv-offloading-size 96 --kv-offloading-backend native在/dev/shm中映射约 103 GB,用于存放被逐出的前缀缓存条目。入口点会在崩溃后移除过期的映射。 - 1,664-token 的调度器警告是预期内的。 DSpark-7 会从 2,048-token 的预算中预留草稿槽位。提高预算会预留更多在途滑动窗口状态,并减少可用的 KV 容量。
- 重启后先预热内核。 首次 prefill 会初始化内核,处理 8.9K token 需要 5.3 秒;后续运行只需 1.7 秒。在接入流量之前,先运行一次未缓存的 prefill。
- 既要测试吞吐量,也要测试正确性。 验证套件包括两轮工具调用测试用例、BFCL 子集(74–76/90 精确调用)、OpenCode 工具 schema 检查,以及在原生和 DSpark 两条路径上的 380K-token 大海捞针召回。冷 prefill 和缓存 prefill 可能走不同的浮点路径,因此两者都要测试。
许可与来源
该技术栈、文档以及源自 vLLM 的叠加层采用 Apache-2.0 许可(见 LICENSE);源自 AITER 的叠加层保留其 MIT 头部声明。每个 diff 的上游基础版本都记录在 patches/README.md 中。模型本身采用 MIT 许可。
参考资料
所有链接均于 2026-08-04 验证。
- DeepSeek-V4-Flash-0731 模型卡 — 官方发布;304B 参数;融合 DSpark 模块;推荐
temperature=1.0, top_p=0.95;MIT 许可 - 官方 vLLM DeepSeek V4 Flash 配方 — 参考启动配置,DSpark(
num_speculative_tokens=7)、FP8 KV、block size 256、deepseek_v4解析器;面向 MI325X/MI355X 的 AMD 指南 - 在 AMD MI300X 上启动 DeepSeek-V4-Flash(Fergus Finn,Doubleword,2026 年 6 月)— 本仓库所基于的启动工作日志:FNUZ 与 OCP FP8 对比、
gfx942上的 AITER 缺口、HIP-graph 隐患、路由 bug - doublewordai/vllm-amd-blog-doubleword — 上述内容的演示 PR,包括 commit
c32932bb9(“按逻辑块大小屏蔽 MXFP4 bitmatrix padding lanes”) - vLLM commit
77469c9— “[ROCm][MLA] Mask the AITER MLA small-head verify flatten causally (#50476)” - vLLM issue #47282 — CPU-KV 加载路径缺少与计算之间的跨流同步(WAR 缺口)
- vLLM PR #47291 — 提议的 WAR 修复,尚未合并;此处以 overlay 形式携带
- AMD Instinct MI300X — 192 GB HBM3,5.3 TB/s 峰值带宽,2.61 PFLOPS 峰值 FP8
- ROCm/AITER — 用于 ROCm 注意力和稠密线性层的 AMD 调优内核库
- vLLM —— 服务运行时(ROCm 每日构建版位于
vllm/vllm-openai-rocm下)
来源:Hacker News 热门(buzzing.cc 中文翻译) · github.com