上个月朋友问我,Windows 上能不能把 vLLM 跑起来?他手头是一台 RTX 4090 24GB,之前一直用 Transformers 写脚本做推理,数据一多就慢得难受,想换 vLLM 这种调度能力强、吞吐高的服务化框架。当时我第一反应是劝退,毕竟 vLLM 官方文档的安装步骤基本默认 Linux 环境,Windows 上直接 pip install 大多会栽在编译环节。结果他坚持要试,我也就跟着踩了一遍坑。折腾三天之后,我把“Windows 上部署 vLLM 并跑通 Qwen3-8B-FP8”这条路线彻底跑通了,整个过程并没有想象中那么难,但有几个细节必须处理到位。这篇文章把完整实操记录写给所有想在 Windows 上做本地大模型服务的人,你不需要是 Linux 高手,只要能跟着命令操作就行。
1. 为什么偏偏是 vLLM + Qwen3-8B-FP8?
1.1 vLLM 到底是什么,本地推理为什么绕不开它
先说清楚一个概念。vLLM 是一个服务于大语言模型推理的开源引擎,最早来自加州大学伯克利分校。它的核心创新是 PagedAttention 和连续批处理,这两个词听起来绕,实际作用很直观:过去推理框架在处理多个请求时,显存里存的 KV Cache 会占用大量碎片空间,并发一高就 OOM;vLLM 把 KV Cache 切成固定大小的“页”,像操作系统管理内存一样按需分配和回收,显存利用率高出一大截。
除了显存管理,vLLM 还自带 OpenAI 兼容的服务接口。也就是说,你只要把服务跑起来,就能用类似调用 OpenAI API 的方式去请求本地模型,接 Dify、接自己写的 FastAPI、接自动评测脚本都很方便。这也是它和大模型部署场景深度绑定的原因。如果你之前只用过 Hugging Face Transformers,你可能会觉得“我写个循环也能做推理”,但并发一上来、请求一密集,vLLM 的优势就是几倍的差距。做一个对比你就懂了:
- Transformers:适合研究模型结构、单条数据处理、训练与微调流程。
- vLLM:适合把模型放到显存里持续服务,支持高并发、批处理和流式输出。
所以我的结论是:只要你是打算“长期跑模型服务”,而不是“临时跑一条数据”,vLLM 就是绕不开的选择。
1.2 Qwen3-8B 为什么适合上车,FP8 又省了什么
Qwen3-8B 是通义千问开源的一个 80 亿参数级稠密模型,擅长中英文任务,代码、数学、通用对话都比较稳。这个体量放在今天的大模型中间,属于“单张消费级显卡刚好能扛”的甜点尺寸:参数不算少,效果可用,部署成本和效果能平衡。
FP8 则是一种量化的高低配组合。标准 FP16 格式下,10 亿参数大约占 2GB 显存,8B 模型的权重就需要 16GB;换成 FP8 之后,10 亿参数大约只要 1GB,8B 模型权重直接降到 8GB 左右。这意味着在 24GB 显存上跑 Qwen3-8B-FP8,权重只占三分之一,剩下的显存可以全部预留给 KV Cache 和并发请求,这是 vLLM 吞吐高的关键。
| 精度格式 | 每10亿参数权重占用 | 8B权重总占用 | 场景建议 |
|---|---|---|---|
| FP16/BF16 | 约 2GB | 约 16GB | 追求最高精度,显存宽裕 |
| FP8 | 约 1GB | 约 8-10GB | 显存有限,追求并发与速度 |
| INT4/AWQ | 约 0.5GB | 约 4-6GB | 显存很小,可接受精度损失 |
Qwen3-8B-FP8 这个版本,官方已经帮你把权重转成 FP8 格式,vLLM 加载时不需要再做额外转换,直接用量化内核跑推理。实际体验下来,生成速度一般比同样模型的 FP16 版本更快,因为权重 IO 减少、计算吞吐更高,而回答质量肉眼几乎看不出差别。
1.3 Windows 上部署 vLLM 的真正难点在哪
很多人在 Windows 上部署 vLLM 失败,第一反应是“工具不行”,但实际上问题出在生态位。vLLM 官方对 Windows 原生的支持一直不是一等公民,源码编译时,flash-attention、xformers 这些底层库都会和 MSVC 工具链产生各种摩擦,C++ 编译器版本对不上就全部报错。
所以通行且稳定的做法是绕开原生 Windows 环境,在 WSL2 或者 Docker Desktop 里跑 vLLM。这两个方案本质上都是跑在 Linux 内核上,但显卡通过 Windows 驱动直接透传进 Linux 子系统,性能损失非常小,实际推理性能接近裸机 Linux。本篇文章主要按 WSL2 原生 Python 环境这条线展开,Docker 作为等价备选方案在第 2 节也会给出命令。
2. 环境准备:先花一小时把地基打牢
2.1 硬件条件与软件清单
先说硬件,显卡必须是 NVIDIA,显存建议 12GB 以上。如果你只有 8GB,跑 Qwen3-8B-FP8 会比较勉强,后面会被迫把上下文长度压得很低。推荐配置如下:
- GPU:NVIDIA RTX 4070 Ti Super 16GB / RTX 4080 16GB / RTX 4090 24GB 均可
- 系统:Windows 11 22H2 及以上,Windows 10 也能用,但更建议 Win11
- 驱动:NVIDIA 最新版驱动,Game Ready 或 Studio 都行,版本新一点没坏处
- Linux 子系统:WSL2,内核版本更新到最新
- Python:WSL2 内安装 Python 3.10 或 3.11
软件层面最关键的顺序是:先装显卡驱动,再装 WSL2,然后在 WSL2 内部装 Python 和 vLLM。千万不要在 Windows 原生 Python 环境里硬试 pip install vllm,虽然某些条件下能装上,但后续 import 阶段大概率会缺一堆动态链接库。
2.2 WSL2 安装,以及那个 14098 报错怎么解
我建议用管理员权限打开 PowerShell,输入:
wsl --install -d Ubuntu-22.04这条命令会自动安装 WSL2 所需的启用项,包括“适用于 Linux 的 Windows 子系统”和“虚拟机平台”。如果系统已经比较干净,装完重启就能进 Ubuntu。不过很多人会在这里遇到一个经典报错:无法启用 Windows 组件“VirtualMachinePlatform”,退出代码 14098。
这个报错的原因通常是系统功能组件没有完整启用。解决办法是在管理员 PowerShell 里手动开启:
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All执行完重启电脑,再试wsl --install -d Ubuntu-22.04。如果还不行,就去 BIOS 里确认 CPU 虚拟化(Intel VT-x 或 AMD-V)已经打开,这一步很多人会漏掉。
装好之后进入 Ubuntu,先跑nvidia-smi确认驱动是否透传。正常会看到显卡型号和驱动版本,如果没有,说明你的 Windows 显卡驱动版本太低,去 NVIDIA 官网更新驱动。
2.3 Docker Desktop 作为等价方案
如果不想在 WSL2 里维护一套 Python 环境,Docker 是更省心的选择。Windows 上安装 Docker Desktop,设置里把后端选成 “WSL 2 based engine”,然后在 Ubuntu 终端里安装 nvidia-container-toolkit。
| 对比项 | WSL2 + Python 虚拟环境 | Docker Desktop 容器 |
|---|---|---|
| 上手成本 | 中,需要管理 Python 包 | 低,镜像里已经封装好 |
| 环境隔离 | 中等,依赖全局 Python | 高,打包即交付 |
| 性能 | 接近原生 | 接近原生,网络稍有开销 |
| 适合场景 | 调试、二次开发 | 快速复现、服务上线 |
我的习惯是开发阶段用 WSL2 原生环境,调试日志方便;给别人复现时提供 Docker 命令。下面把两种启动 vLLM 的方式都写出来,你按习惯选一种。
2.4 Python 虚拟环境和 vLLM 安装
进入 Ubuntu WSL2,用 conda 创建独立环境:
conda create -n vllm python=3.10 -y conda activate vllm pip install --upgrade pip setuptools wheel pip install vllm如果你机器网络情况不错,pip 会直接拉取官方预编译轮子,几分钟完成。很多朋友会问 vLLM 构建需要多长时间,这里要分情况:如果你只是pip install vllm,那不是源码构建,下载完就能用;如果你从源码编译git clone后执行pip install -e .,那 flash-attention 和 vllm 整体编完,在 8 核机器上可能要 30~60 分钟。不建议新手一上来就源码编译,预编译轮子完全够用。
装完之后验证一下:
python -c "import vllm; print(vllm.__version__)"如果能正常打印版本号,环境这关就算过了。
3. 模型下载与文件准备
3.1 Qwen3-8B-FP8 的目录结构先看清楚
模型下载不是只下载一个文件就完事。Qwen3-8B-FP8 在 Hugging Face 上是一个完整仓库,里面至少包含这些内容:
config.json generation_config.json merges.txt model-00001-of-00004.safetensors model-00002-of-00004.safetensors model-00003-of-00004.safetensors model-00004-of-00004.safetensors model.safetensors.index.json tokenizer.json tokenizer_config.json vocab.json其中最关键的是config.json,里面会标注模型的量化方式。Qwen3-8B-FP8 的 config 里通常有quantization_config相关字段,vLLM 启动时会自动读取并加载 FP8 推理 kernel。分片权重文件一般有 4 个左右,总大小约 9~10GB,下载时不要只下第一个分片,否则加载到一半会报找不到权重。
3.2 下载、校验与落盘位置
在 WSL2 里,最稳的下载方式是使用 Hugging Face 官方的下载命令行工具。先安装huggingface_hub:
pip install -U huggingface_hub hf download Qwen/Qwen3-8B-FP8 --local-dir /mnt/d/models/qwen3-8b-fp8这里我把模型放在/mnt/d/models/qwen3-8b-fp8,也就是 Windows 的 D 盘。这样做的原因很实际:WSL2 的系统盘默认在 C 盘,一个大语言模型动辄 10GB,如果全堆在 C 盘,过几天系统盘就红了。放 D 盘还有一个好处,后面多个模型之间可以共用磁盘空间,不需要重新分配。
下载完一定要校验文件完整性,至少看一眼总大小,如果只有几百 MB,多半是断点下载不完整。hf download本身会做部分校验,但我还是会手动用ls -lh检查分片大小是否接近预期值。
3.3 调整缓存目录,避免系统盘爆炸
vLLM 和 Transformers 都会把下载过程中的临时文件放到默认缓存目录~/.cache/huggingface。如果你后面还要试其他模型,我建议在~/.bashrc里固定一个环境变量:
echo 'export HF_HOME=/mnt/d/models/hf_cache' >> ~/.bashrc source ~/.bashrc这样无论下载还是读取模型,所有缓存都在 D 盘,系统盘压力小很多。实测在只跑一个模型时,这个操作看不出差别,但当你连续换三四个模型做对比时,缓存复用能省下大量流量。
4. vLLM 服务启动与接口调试
4.1 最小启动命令,先把服务跑起来
环境准备好之后,第一次启动不要用花哨参数,先跑最小配置:
conda activate vllm python -m vllm.entrypoints.openai.api_server \ --model /mnt/d/models/qwen3-8b-fp8 \ --served-model-name qwen3-8b \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.9 \ --max-model-len 32768--model指向模型目录,--served-model-name是暴露给客户端的模型名,--tensor-parallel-size 1表示只用单卡,--gpu-memory-utilization 0.9表示最多允许 vLLM 占用 90% 显存,--max-model-len 32768设置最大上下文长度。
首启动会看到一段日志,然后加载权重,通常需要几十秒到几分钟,具体取决于磁盘速度和显存大小。看到Starting vLLM server或者 Uvicorn running 字样,说明服务已经起来了。
4.2 常用启动参数逐个说清楚
参数不是越多越好,但下面这几个你迟早会遇到:
| 参数 | 作用 | 我的建议 |
|---|---|---|
--tensor-parallel-size | 多卡并行度 | 单卡填 1,多卡填卡数 |
--gpu-memory-utilization | 限制 vLLM 最大显存占用 | 0.85~0.92 比较稳 |
--max-model-len | 最大上下文长度 | 显存小就降到 8192 |
--dtype | 推理时加载的数据精度 | auto 即可,vLLM 自动识别 FP8 |
--quantization | 指定量化核对 | 默认自动,除非识别异常才手动指定 |
--enforce-eager | 关闭 CUDA Graph | 遇到显存不足或兼容性问题时开 |
--host/--port | 监听地址和端口 | 默认 0.0.0.0:8000 |
这里特别说一下--max-model-len。它不只是限制输入长度,还会影响 KV Cache 的预分配大小。如果设得太大,比如 131072,即使实际请求不长,vLLM 也会先预留大量显存来准备 KV Cache,导致能并发处理的请求变少。24GB 显卡跑 8B 模型,32768 是一个体验不错的起点。
4.3 从启动日志看懂 vLLM 的加载顺序
排错时,最大的法宝是看懂启动日志。vLLM 启动模型时的执行文件顺序基本是固定的:
- 读取
config.json,确认模型结构和量化方式。 - 加载 tokenizer 相关文件,包括
tokenizer.json和merges.txt。 - 读取
model.safetensors.index.json,定位分片权重。 - 按分片顺序加载 safetensors 权重到显存。
- 初始化 GPU 内存、分配 KV Cache。
- 启动异步引擎和 HTTP 服务。
如果日志卡在第 3 步,说明权重文件不完整;卡在第 4 步并且显存报错,说明显存不够或者--max-model-len太大;卡在第 1 步就报错,多半是模型路径指向错了。学会看这个顺序,比乱猜问题高效得多。
4.4 用 OpenAI 风格接口测一轮推理
服务启动后,先用下面的命令确认模型已在列表里:
curl http://localhost:8000/v1/models如果返回结果里有qwen3-8b,说明服务正常。然后发一个对话请求:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3-8b", "messages": [{"role": "user", "content": "用一句话介绍 FastAPI"}], "temperature": 0.7 }'返回的 JSON 结构和 OpenAI 的接口很像。拿到这个结果后,你可以直接用 Python requests 或 OpenAI SDK 继续封装,后面接 Dify 或者其他自动化工作流都不是问题。
5. 性能评测:用 vllm bench serve 压测一下
5.1 压测工具怎么用
vLLM 自带压测脚本,命令行入口是vllm bench serve。参考下面的命令:
python -m vllm.bench.benchmark_serving \ --model qwen3-8b \ --base-url http://localhost:8000/v1 \ --tokenizer /mnt/d/models/qwen3-8b-fp8/tokenizer.json \ --request-rate 8 \ --num-prompts 200--num-prompts是发送的总请求数,--request-rate表示每秒发多少请求。比如设置成 8,就是模拟每秒 8 个请求打过来,看看服务能不能扛住。如果你只想做单流测试,可以把--request-rate设为 1,这样一次一个请求,重点看首 Token 延迟。
5.2 压测指标怎么读
压测结束会输出一堆指标,我最关心的有四类:
| 指标 | 含义 | 关注点 |
|---|---|---|
| request throughput | 每秒处理请求数 | 越高越好 |
| output token throughput | 每秒生成 token 数 | 反映大模型实际生成能力 |
| TTFT | 首 Token 延迟 | 体感响应速度 |
| TPOT | 每个 Token 平均生成耗时 | 影响流式输出体验 |
以 RTX 4090 24GB 跑 Qwen3-8B-FP8 为例,在上下文 8K、并发 8 的情况下,output token throughput 通常能到 150~250 tokens/s,TTFT 多在几百毫秒到 1 秒之间。这个数字不是固定值,会受请求长度、并发数、CPU 能力影响,你的机器跑到 100 tokens/s 以上已经说明部署没有明显瓶颈。
5.3 压测完该怎么调优
如果压测时出现排队严重、响应变慢,优先看 GPU 显存够不够。当--gpu-memory-utilization设置过高而模型本身又吃显存时,KV Cache 可用空间会变小,并发一高就开始排队。
常见的调整思路是:显存紧张就降低--max-model-len,从 32768 降到 16384;并发上不去就提高--gpu-memory-utilization,比如从 0.9 提到 0.95;如果还出现奇怪的计算错误,就加--enforce-eager关掉 CUDA Graph 优化,虽然速度会掉一点,但稳定。
6. 常见问题与避坑清单
6.1 VirtualMachinePlatform 14098 错误的完整处理流程
这是一个 Windows 特有的硬伤,我前面已经提过一次。再补充一个排查思路:如果Enable-WindowsOptionalFeature执行后仍然报 14098,打开“设置-系统-可选功能-更多 Windows 功能”,手动勾选“虚拟机平台”和“适用于 Linux 的 Windows 子系统”,然后重启。如果图形界面也勾不上,那就确认 BIOS 里的虚拟化开关,这是最后的兜底方案。
6.2 [pynccl.py:113] vLLM is using nccl==2.30.7 是不是报错?
很多人第一次启动时看到这行日志会慌:[pynccl.py:113] vllm is using nccl==2.30.7。放心,这是正常日志,不是错误。NCCL 是 NVIDIA 的 GPU 通信库,vLLM 打印它只是告诉你当前用了哪个版本的 NCCL。单卡场景下它甚至不会发挥太大作用,只有当--tensor-parallel-size大于 1 需要多卡通信时,NCCL 才是关键。
如果你确实在跑多卡,并且遇到通信超时或卡死,可以尝试设置环境变量:
export NCCL_P2P_DISABLE=1 export NCCL_SHM_DISABLE=1这两个参数会关闭一些直连和共享内存通信方式,降低稳定性风险,但通信效率可能略有下降。高效多卡方案可以参考官方文档,这里只给应急处置。
6.3 显存不足的时候,停止较劲直接减配置
如果你在 16GB 显卡上跑 Qwen3-8B-FP8,最常碰到的错误是CUDA out of memory。碰到先按顺序尝试三步:把--max-model-len降到 8192;把--gpu-memory-utilization从 0.9 降到 0.8;都没解决就加--enforce-eager。如果三步做完还是 OOM,就要考虑换更小模型或者减少并发。本地部署追求的是稳定可复现,不要硬把一个吃满显存的配置当生产标准。
6.4 SGLang、LM Studio 和 vLLM 到底怎么选
这几个工具常被放在一起讨论,但定位差异很大。
SGLang 是另一个高性能推理框架,设计思路和 vLLM 有交叉也有区别。它更强调复杂推理加速和结构化生成控制,性能表现也很强。但如果你已经用 vLLM 跑通了 Qwen3-8B-FP8,没有必要强行迁移,先用顺手的更重要。SGLang 适合追求极致吞吐、并且愿意折腾配置的进阶用户。
LM Studio 则是另一种产品,带图形界面,内置了 Bionic 运行时,适合完全不想碰命令行的桌面用户。它跑小型量化模型很方便,双击就能用。但它的定位更偏向“个人桌面助手”,在多用户并发、批量接口和精细化参数控制上不如 vLLM 灵活。打个比方:LM Studio 像家电,vLLM 像专业厨房设备,你要做一顿家庭晚餐,家电很合适;但你要开餐厅出餐,还是得专业设备。
6.5 几个 Windows 侧的小习惯建议
最后分享几个比较零碎但实用的经验。
第一,不要在工作目录带中文路径或空格。Windows 下 D 盘模型目录如果叫qwen3 模型,传到 WSL2 后引用起来很容易踩坑,建议全部用英文加下划线。
第二,Windows 安全中心偶尔会扫描模型文件导致加载变慢,如果你在 WSL2 里加载权重时发现磁盘 IO 很高,可以在 Windows 侧把模型目录临时加入排除列表。这只是性能优化建议,根据个人风险偏好决定是否操作。
第三,如果你还需要部署其他 AI 相关桌面工具或把 vLLM 作为后端服务,比如接 Dify 这类低代码平台时,尽量让 vLLM 监听0.0.0.0:8000,这样宿主机和容器都能访问。
我个人在实际操作中的体会是:Windows 部署 vLLM 最大的难点从来不是 vLLM 本身,而是环境组合的复杂度。只要你把 WSL2、NVIDIA 驱动、Python 虚拟环境这三件事理顺,后面跑 Qwen3-8B-FP8 的时间和 Linux 上几乎没有差别。最后再分享一个小技巧:第一次完整跑通后,把启动命令写成一个 shell 脚本放到固定目录,下次只需要激活 conda 环境再执行一行脚本,整个服务就能拉起来,省去每次敲长命令的麻烦。希望这篇实战记录能帮你少走几个小时的弯路。