【保姆级教程】RTX 4090 部署 DeepSeek-V4-Flash 全攻略(MXFP4 量化 + 128K 上下文)
前言
-
模型说明:DeepSeek-V4-Flash 官方原生支持 1M(100 万 token)上下文,本文通过参数限制为 128K 降低显存压力。
-
硬件限制:RTX 4090 24G 仅支持 INT4/MXFP4 量化,FP8/FP16 显存不足,且 4090 无原生 FP8 硬件加速,INT4/MXFP4 才可行,显卡不足建议部署采用 CPU/GPU 混合卸载部署,内存得用DDR5以上带宽的。
-
部署引擎:全量GPU部署显存压力过大,要求5090以上显卡配置。且vLLM不支持内存卸载,推荐使用ktransformers推理引擎部署,也可使用llama.cpp。内存卸载方案建议内存256G。
-
性能预期:INT4/MXFP4至少2张 4090 起步,要求有一定并发和较长上下文窗口建议4张起显卡。另外,显卡不足还可考虑Q2、Q3模型。
一、环境准备
基础环境及版本要求如下:
| 组件 | 版本 | 说明 |
| ktransformers | ≥ 0.6.2 | v0.6.2 首次原生支持 DeepSeek-V4-Flash (PR #1970:kt-kernel MXFP4 MoE + sglang hybrid inference), 实用v0.6.4 |
| Python | 3.10 / 3.11 | 建议3.11 |
| CUDA | ≥ 12.8 | 官方文档要求 12.8+(含 4090),可选12.8或13.0,实用12.8 |
| NVIDIA 驱动 | ≥570(CUDA 12.8 兼容) | 可直接下载 CUDA+NVIDIA 驱动 组合包 https://developer.download.nvidia.com/compute/cuda/12.8.0/ local_installers/cuda_12.8.0_570.86.10_linux.run |
| transformers | == 4.57.1(必须钉版) | 5.x 会让 DeepSeekV4Config 报 TypeError,必须手动钉 4.57.1。在线安装 sglang-kt 0.6.4会连带装transformers。 |
| flashinfer | ≥ 0.6.9(flashinfer-python + flashinfer-cubin 同版本) | V4-Flash 的 MXFP4 MoE 模块需要 0.6.9 才有的 mxfp8_quantize 等 API。版本下载准确否则后期折腾起来很痛苦。 |
| tilelang | == 0.1.8 | 4090 必装——NSA sparse-MLA indexer 在非 Hopper GPU 上走 tilelang 路径。 |
| sglang | kvcache-ai fork(ktransformers 内置 submodule) | 不是上游 sglang,是 KT 专用 fork。选在线装sglang-kt的话会连带。 |
1. 基础环境配置
推荐使用 Ubuntu 22.04 系统,搭配 CUDA 12.8+,NVIDIA 驱动 ≥ 570,python ≥ 3.10, ktransformers ≥ 0.6.2:
# 创建并激活虚拟环境
conda create -n deepseek python=3.11 -y
conda activate deepseek
2. 安装 ktransformers 与依赖
# 1. 克隆 ktransformers(含全部 submodule)
git clone https://github.com/kvcache-ai/ktransformers.git
cd ktransformers
git submodule update --init --recursive
# 2. 编译 KT-Kernel(C++/CUDA 扩展,10-20 分钟)
cd kt-kernel && ./install.sh && cd ..
# 3. 安装 SGLang(kvcache-ai 专用 fork,不是上游 sglang)
./install.sh
# 4. 关键依赖(三个必须钉版/版本)
pip install --upgrade flashinfer-python flashinfer-cubin # ≥0.6.9,两个包同版本
pip install "transformers==4.57.1" # 必须!5.x 会报 TypeError
pip install tilelang==0.1.8 # 4090 必装!NSA sparse-MLA 路径
# 5. 验证
python -c "import ktransformers; print(ktransformers.__version__)" # 期望 ≥0.6.2
能在线安装推荐在线安装,直接pip install kt-kernel sglang-kt即可,pip可用国内镜像源比github官网下载速度更快且更方便。具体可参考文档 KTransformers Docs
二、下载 DeepSeek-V4-Flash 模型
1.下载路径
国内用户优先使用 魔搭社区(ModelScope) 下载,速度更快:
| 优先级 | 地址 |
|---|---|
| Q4首选 | DeepSeek-V4-Flash-GGUF |
| Q4可选 | DeepSeek-V4-Flash-GGUF |
| 官方原版,MXFP4可用 | DeepSeek-V4-Flash |
| 官方0731原版,MXFP4首选 | DeepSeek-V4-Flash-0731 |
2.模型选择
这里我用的 kt 部署的官方0731原版,安全稳定可靠。部署Q4的话首选Unsloth 这个仓库,推荐下载 UD-Q4_K_XL,可使用llama.cpp部署。
官方0731原版下载:

Q4模型下载:

| 量化方案 | 位宽 | 文件大小 | 你这套机器的评价 |
|---|---|---|---|
| UD-Q4_K_XL | 4-bit | 155 GB | ✅ 首选——Unsloth 自家推荐,跟标准 Q4_K_M 效果对齐,200GB 内存宽宽松松 |
| UD-IQ4_NL / UD-IQ4_XS | 4-bit iMatrix | 138 GB | ✅ 备选——重要性加权 4-bit,部分基准反而略好;想留更多内存余量时选这个 |
| UD-Q3_K_M / UD-Q3_K_XL | 3-bit | 129 GB | ⚠️ 仅在你实际只有 192GB、想跑更长上下文时考虑,质量会降 |
| UD-IQ3_S | 3-bit iMatrix | 117 GB | 同上,但要 3-bit 时比 Q3_K_M 更值 |
| UD-Q8_K_XL | 8-bit | 162 GB | ❌ 你这套机器跑没意义——只有 4 卡 24G,仍需卸载,不如直接用 Q4 |
| UD-Q2_K_XL / UD-IQ2_* | 2-bit | 91–97 GB | ❌ V4-Flash 量化损失过大,长链推理会瞎 |
| UD-IQ1_S / UD-IQ1_M | 1-bit | 83–87 GB | ❌ 极端压损,不适合生产 |
三、RTX 4090 部署核心配置
1. 启动服务
#!/bin/bash
# ========== 4090 专属环境变量 ==========
export CUDA_VISIBLE_DEVICES=0,1,2,3
export FLASHINFER_CUDA_ARCH_LIST=8.9a # SM_89 = RTX 4090
export TORCH_CUDA_ARCH_LIST="8.9+PTX"
export SGLANG_DSV4_MODE=2604 # V4-Flash 必须
export SGLANG_DSV4_2604_SUBMODE=2604B # V4-Flash 必须,缺失会报 swiglu_limit 断言
# ========== 新增gcc配置、禁用NPU ==========
export CC=/usr/bin/gcc
export CXX=/usr/bin/g++
export NVCC_CCBIN=/usr/bin/g++
export SGLANG_USE——NPU=O
export SGLANG_DISABLE_NPU=1
export SGLANG_BACKEND=cuda
# ========== 启动 SGLang + KT-Kernel 服务 ==========
numactl --interleave=all python -m sglang.launch_server \
--host 0.0.0.0 \
--port 8000 \
--model /data/models/DeepSeek-V4-Flash \
--kt-weight-path /data/models/DeepSeek-V4-Flash \
--kt-method MXFP4 \
--kt-num-gpu-experts 20 \
--kt-cpuinfer 64 \
--kt-threadpool-count 2 \
--kt-gpu-prefill-token-threshold 2048 \
--kt-enable-dynamic-expert-update \
--tensor-parallel-size 4 \
--context-length 131200 \
--attention-backend flashinfer \
--mem-fraction-static 0.85 \
--chunked-prefill-size 4096 \
--max-prefill-tokens 4096 \
--max-running-requests 3 \
--watchdog-timeout 1800 \
--disable-shared-experts-fusion \
--trust-remote-code \
--cuda-graph-bs 1 \
--cuda-graph-max-bs 1 \
--disable-radix-cache \
--skip-server-warmup \
--tool-call-parser deepseekv4 \
--reasoning-parser deepseek-v4
关键参数说明
| 参数 | 说明 | 4×4090 调优 |
|
| CPU 专家用 MXFP4 精度计算(官方 FP4 原版权重直接用) | 默认 |
|
| 放在 GPU 上的路由专家数量 | 4 卡 96GB 可放 20–30 个(每个约 0.5GB),根据并发数、上下文窗口、显存占比 及自身速度要求进行调节。 |
|
| CPU 推理线程数 | ≈ 物理核心数(留几个给系统) |
|
| CPU 线程池数 | 双路 CPU 可设 2–4 |
|
| 4 卡张量并行 | = 4090 数量 |
|
| 上下文长度 | 可根据内存大小进行调整,先按32K 起步,有余量再加到128K,要结合并发数、显存占比进行调节 。 |
|
| 静态显存占用比例 | 0.85–0.90 |
|
| 最大并发请求数 | 4090 offload 方案,个人使用建议 1-2个,企业内部用5-20个。 |
|
| V4-Flash 必须设置 | 缺失会报 swiglu_limit assertion error |
|
| 4090 专属,告诉 flashinfer JIT 编译 SM_89 kernel | 5090 是 12.0a |
首次启动耗时 4–10 分钟(权重加载 + MXFP4 swizzling + CUDA Graph 捕获)。
2.服务化与验证
健康检查:
# 模型列表
curl http://192.168.x.x:8000/v1/models
# 对话测试(官方推荐 temperature=1.0, top_p=1.0)
curl http://192.168.x.x:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-V4-Flash",
"messages": [{"role": "user", "content": "你好,介绍一下你自己"}],
"temperature": 1.0,
"top_p": 1.0,
"max_tokens": 256
}'
客户端接入:
Dify / Chatbox / Cherry Studio / OpenAI SDK 填:
base_url:http://x.x.x.x:8000/v1api_key: 任意值(SGLang 默认不校验,可加 nginx 前置鉴权)model:deepseek-ai/DeepSeek-V4-Flash
四、部署成功后测试
1. OpenAI 兼容 API 调用
部署成功后,服务默认运行在 http://localhost:8000/v1,兼容 OpenAI 接口格式,可直接用 OpenAI SDK 调用:
from openai import OpenAI
# 初始化客户端
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="dummy" # 本地部署无需真实 API Key,填任意值即可
)
# 对话测试
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[
{"role": "system", "content": "你是一个 helpful 的助手。"},
{"role": "user", "content": "请用 100 字介绍一下 DeepSeek-V4-Flash。"}
],
temperature=0.7,
max_tokens=1024
)
print("模型回复:", response.choices[0].message.content)
2. 浏览器 Web 界面测试
可使用 Dify、Opencode 连接本地部署的 DeepSeek-V4-Flash模型,实现可视化对话。
五、常见问题
1. 依赖版本冲突
-
pytorch版本冲突问题最常见,建议安装torch==2.9.1或者2.5.0版本的,注意安装GPU版本的,且要CUDA版本匹配。
-
NCCL版本冲突问题也比较多,从国内镜像安装的torch不带NCCL,单独安装可能会有版本冲突问题需要自行调整。可以选择去pytorch官网上下载安装pytorch,会自带NCCL。
-
CUDA版本冲突,这个情况可能会保持找不到CUDA等,要安装与ktransformers适配的cuda版本。
-
tilelang、apache-tvm-ffi、flashinfer-python、flashinfer-cubin未安装或安装的版本不匹配,可单独使用pip install tilelang==0.1.8等方式安装适配版本。
-
gcc和g++版本问题,安装一致的版本即可解决。另外增加环境变量“CC=/usr/bin/gcc”、“CXX=/usr/bin/g++”、“NVCC_CCBIN=/usr/bin/g++”。
2. 生成速度很慢
-
部分权重放在CPU中调用起来会稍微慢一点是正常的。
-
模型常驻 GPU的专家数越多,速度越快。有一定概率会命中到 GPU的专家,此时输出速度要比命中到 CPU的专家的速度快很多。
-
上下文窗口--context-length、并发数 --max-running-requests、常驻GPU专家数 --kt-num-gpu-experts、控制权重 + CUDA Graph + KV pool 占用显存的比例 --mem-fraction-static 这几个参数都对速度有影响,需要根据实际情况权衡。
-
多卡并行可显著提升速度,预算受限的情况还得忍忍。
3. 无法调用工具
-
一般vLLM部署的模型无法调工具增加--enable-auto-tool-choice、--tool-call-parser hermes这2个参数即可解决。Kt部署的DS--V4-Flash,实测需要增加--tool-call-parser deepseekv4、--reasoning-parser deepseek-v4这2个参数。
4. 精度下降明显
-
INT4/MXFP4 量化会轻微损失精度,对话、写作场景无明显影响。
六、部署经验
6.1 mem-fraction-static参数说明
mem-fraction-static 0.75为例:
| 部分 | 占谁的预算 | 例子 |
|---|---|---|
| 静态:模型权重(含 GPU 专家) | 从 0.75 里扣 | 稠密层 + 专家权重,常驻 |
| 静态:KV 缓存池 | 0.75 扣完权重后的剩余 | 预分配,按并发×上下文使用 |
| 动态:运行时临时开销 | 0.25 的余量里 | 激活值、临时缓冲、CUDA 上下文、CUDA Graph 捕获、专家换入换出的搬运缓冲、显存碎片 |
模型的实际占用是:提问时瞬时占用 = 权重 + KV池(≤0.75) + 动态开销(来自0.25)
提问时总量可能超过 0.75——激活值和临时缓冲就是从 0.25 里现拿的,用完全部释放。0.25 不是“预留不用”,而是“随用随取的安全垫”。
两个常见误解
-
“模型所有能用得上的显存 = 0.75” ❌
动态部分(激活、graph 捕获、专家搬运)用的就是 0.75 之外的空间,只是不常驻、不预分配。 -
“0.25 完全闲置” ❌
它平时看起来闲着,提问时会被激活值等临时借用;而且 CUDA 上下文本身要先占约 0.5~1GB/卡,实际动态余量比 25% 略少。
调 mem-fraction 的本质
它是在静态 KV 容量和动态安全余量之间做分配:
- 0.85:KV 池更大(能扛更多并发×上下文),但动态余量只剩 15%,提问时激活值一涨就容易 OOM;
- 0.75:KV 少一点,但动态余量 25%,运行更稳;
- 0.6:KV 更少,动态余量 40%,最稳但并发/长上下文容量最小。
6.2 kt-gpu-prefill-token-threshold填2048和4096优劣势
2048 和 4096 的差别只有一个:2K~4K 这个区间的提示词走哪条路。4K 以上两种值都走 layerwise,2K 以下两种值都走常规 GPU,完全无差别。
2048 的优劣势
| 说明 | |
|---|---|
| 优势 | 2K~4K 的提示也走 layerwise:单次预填充的峰值显存更可控,高并发下多个中等长度请求同时 prefill 时更不容易 OOM;这也是官方 Docker 镜像的默认值 |
| 劣势 | 2K~4K 的提示反而变慢:layerwise 有逐层开销,且第一个触发它的请求要承担一次性的槽位分配成本;如果你们这种长度流量多,TTFT 会差一点 |
4096 的优劣势
| 说明 | |
|---|---|
| 优势 | 2K~4K 提示走常规 GPU 预填充:这个区间 TTFT 更快;与官方教程源码示例的值一致(教程 5090 示例用的就是 4096) |
| 劣势 | 2K~4K 提示的预填充峰值显存更高(整段一次处理),高并发下显存压力略大 |
实际的影响
先看流量分布:
- 短问答(几个字到几百 token):远低于两个阈值 → 填 2048 还是 4096 完全没区别,主要场景不受影响;
- 长文档(≥4K):两种值都走 layerwise → 也没区别;
- 只有 2K~4K 的中等长度请求才是分水岭:4096 更快但更吃显存,2048 更稳但略慢。
建议
使用 4096 ——它和文档、官方示例一致,短问答流量不经过这个分界。只有一种情况值得改成 2048:压测发现多个 2K~4K 请求并发 prefill 时显存吃紧或 OOM,这时降阈值让它们走更省显存的 layerwise 路径。
6.3 skip-server-warmup参数必要性
skip-server-warmup参数是控制预热的,官网示例中保留了这个参数,去掉 = 让服务启动时就把预热做完(CUDA Graph 捕获、内核编译、自动调优、dummy 前向),代价是启动时间变长。优缺点对比如下:
1.去掉(即启动时预热)的优点
(1)第一个真实请求就是快的。不会有“服务已就绪但第一个请求要现场编译内核、捕获 CUDA Graph”的冷启动惩罚——对对外 SLA 或“运维启动后直接交用户”的场景很关键。
(2)错误提前暴露在启动阶段,预热相当于一次冒烟测试:如果 4090 内核缺失、flashinfer 版本不对、显存不足,启动时就会报错,而不是等第一个用户请求时才炸。
(3)行为可预期。看到 “The server is fired up and ready to roll!” 就代表真的 ready,而不是“半 ready”。
2.去掉的缺点
(1)启动时间明显变长。现在你们启动约 4~10 分钟(权重加载 + MXFP4 重排),预热会把 CUDA Graph 捕获和内核编译加进启动阶段,可能再多几分钟。你们现在正处于频繁改参数、反复重启调优的阶段,每轮多等几分钟会很难受。
(2)重启迭代变慢。调 --kt-num-gpu-experts、--mem-fraction-static、上下文长度都要重启,去掉这个参数等于每次重启都附带完整预热。
(3)不是“一次预热,永久全快”。SGLang 启动预热用的是固定 dummy 形状,真实请求如果形状差异大(比如超长 prefill、不同 batch),第一个这种请求仍可能触发新的编译/捕获。所以它消除的是“公共部分”的冷启动,不是所有情况。
(4)偏离官方教程的验证配置。官方 DSV4 教程的命令是带 --skip-server-warmup 的,去掉属于主动偏离(合理,但要知道自己在改什么)。
建议:
调优期:保留 --skip-server-warmup,启动快,重启迭代效率高。启动后手动发一个代表性请求预热(前面说过的方法)。
生产:两个选择
(1)直接去掉它,让启动阶段吸收预热成本(适合 SLA 严格、不允许首个用户吃冷启动);
(2)保留参数,但在启动脚本里自动加一步 warmup:服务 ready 后脚本自动 curl 一个代表性请求再对外开流量。这样兼顾“重启快”和“首个用户快”。
6.4 kt-threadpool-count 参数解析
--kt-threadpool-count 2 是 kt-kernel CPU 侧专家计算的线程池数量,要和 --kt-cpuinfer 配合理解:
两个参数的关系
| 参数 | 含义 | 你的值 |
|---|---|---|
--kt-cpuinfer | CPU 推理线程总数(= 物理核心数) | 64 |
--kt-threadpool-count | 把 64 个线程分成几个线程池(= NUMA 节点数) | 2 |
也就是说:64 个线程分成 2 个池,每池 32 个线程。每个池绑定到一个 CPU(NUMA 节点)上运行,只处理/优先访问该节点的内存。
设置不对会怎样
1:双路机器只有一个池 → 一个节点闲置,吞吐明显下降;4:每节点挤 2 个池 → 线程争抢同一节点的内存控制器,性能反而变差;- 单路机器(1 个节点):设 2 反而多余,应设 1。
6.5 主要参数之间的关系
--mem-fraction-static 是“静态预算”(权重 + KV 池)的总开关;--kt-num-gpu-experts 决定这个预算里权重占多少,--context-length 和 --max-running-requests 决定 KV 池被请求“消耗”多少。
| 参数 | 对 mem-fraction 预算的影响 | 本质 |
|---|---|---|
--kt-num-gpu-experts ↑ | 权重占用 ↑ → KV 池 ↓(总量不变,专家从池子里挤) | 供给端:占预算 |
--context-length ↑ | 不改变池子大小,但单请求占池上限 ↑ → 更容易 pool full | 需求端:消耗池 |
--max-running-requests ↑ | 不改变池子大小,但同时消耗池的请求数 ↑ → 更容易排队/被拒 | 需求端:消耗池 |
关键点:
- context-length 和 max-running-requests 不会让显存占用变多(池子启动时就按 mem-fraction 定死了),它们只是决定“这个池子够不够用”;
- 只有 kt-num-gpu-experts 会真实改变池子大小——因为专家权重从 0.75 的预算里优先扣,扣完剩多少,KV 池才有多少。
测试调优时每次只动一个变量:改专家数后看日志里的 max_total_num_tokens 和压测是否出现 KV cache pool is full,用数据判断是该调 mem-fraction、还是降上下文/并发、还是少放几个专家。
6.6 部署后的prefill和decode
部署后后台日志可看到prefill和decode,具体来讲一次请求分两个阶段:
| 阶段 | 干什么 | 特点 |
|---|---|---|
| prefill(预填充) | 把整个输入从头到尾过一遍,算出 KV 缓存 | 一次性处理全部输入,计算重、占内存 |
| decode(生成) | 逐字生成输出 | 每步只处理 1 个新 token,步数多、延迟敏感 |
6.7 CUDA Graph失败会有什么影响
CUDA Graph 的价值是把一整个 decode 步的内核序列提前录制成图,每步只做一次极低开销的回放,省掉每步的 CPU 启动开销。
SGLang 捕获 CUDA Graph 失败时,默认回退到 eager 执行(每步正常调度内核),服务继续运行,日志里出现类似 “Failed to capture CUDA graph, falling back to eager mode” 的警告。正确性不受影响,模型照样答得对,只是慢。
失败回退 eager 后:
- decode 变慢:每步多一次次内核启动/调度的 CPU 开销,batch 越小、步数越多,损失占比越大;
- 低并发场景损失最明显:这正是你要“快”的优先级场景,和高并发长文本(本来就允许慢)正好相反;
- CPU 占用可能上升:eager 模式每步都要 CPU 参与调度,负载更高。
6.8 什么时候才会报OOM
“长请求/高并发”会使得0.75的显存池用满,“池子满→排队”不会 OOM,但运行期的动态开销有概率把剩余显存吃穿会报OOM。
6.9 多卡部署时第一张卡会多用显存
这是 TP 架构的正常特性:
| 来源 | 说明 |
|---|---|
| 主进程角色 | 模型加载、tokenizer、初始化都从 rank 0 发起 |
| logits 聚合/采样 | TP 下采样在 rank 0 做,要把 4 卡的 logits 片段收拢(DeepSeek 128K vocab 下,并发高时这个缓冲有点分量) |
| CUDA graph 捕获 | rank 0 上的临时 buffer 通常比其它卡大一些 |
另外,调度器(scheduler)是跑在 CPU 侧的 Python 进程里的,负责排队、组 batch、决定谁 prefill 谁 decode,它占的是内存,几乎不占 GPU 显存,与多占用的显存无关。
什么时候会真的 OOM
启动期(模型加载时):
-
权重(稠密层 + GPU 专家)超出显存总量,或超出 mem-fraction 预算——比如专家数设得太大、mem-fraction 设得接近 1;
-
表现为:启动到一半报错退出,服务根本起不来。
运行期(动态分配时),常见触发点:
-
激活值峰值:预填充/解码的中间张量。虽然
--chunked-prefill-size 2048限制了每块激活,但有些算子按“整批 token 数”或“最大上下文”分配工作区(attention workspace、logits、CUDA Graph 捕获),10 路 × 128K 同时 prefill 时这些一次性分配可能很大; -
CUDA Graph 捕获:捕获时需要额外显存,余量不足就失败;
-
动态专家换入换出:
--kt-enable-dynamic-expert-update搬运专家时需要临时缓冲,余量接近 0 时最容易炸; -
显存碎片:
memory.free显示有空间,但凑不出一块连续的大块,分配失败(本质也是 OOM); -
DSpark 投机解码:草稿/验证路径有自己的工作区,会额外吃动态显存。
七、总结
-
RTX 4090 24G 可以部署 DeepSeek-V4-Flash,核心是 INT4/MXFP4 量化 + 限制 128K以内 上下文限制。
-
双卡可跑,4卡性能更稳,速度与并发能力显著提升。
-
部署后的服务兼容 OpenAI API,可直接对接各类应用与工具。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)