概述
一个 开源的支持高并发的高性能大模型推理引擎。在这篇博客有简单提到过。
modelscope
通过vLLM(或其他平台、框架)部署模型前,需要先下载模型。国内一般使用 魔搭社区,模型库里搜索想要下载的模型。输入qwen3会看到很多个候选项,主要是:
- 参数量不一致;
- 量化版本不一致;
- 提交者不一致。
总之,找到模型下载路径(/Qwen/Qwen3-30B-A3B)是需要花点时间的。
下载模型有多种方式:
- 通过浏览器下载:打开魔搭页面,默认下载到
C:\Users\johnny\Downloads目录下。模型文件通常非常大,如Qwen3-30B-A3B-FP8,分割为7个文件共30+G。Chrome下载效果如下,不便之处在于文件名可辨识度非常低,最后极有可能不知道下载下来的是哪个模型的子文件。而且这么做,也不太专业。 - 通过命令行下载:在有Python和pip的环境下,
pip install modelscope安装modelscope。使用modelscope命令行下载,如下载reranker模型:modelscope download --model BAAI/bge-reranker-v2-m3 --local_dir /home/models/BAAI/bge-reranker-v2-m3。 - 通过客户端下载:
vim ms_download.py,填入如下内容
embedding
使用BAAI提供的模型,docker启动命令(一行):
docker logs -f <container_id>查看日志:

实际上,上述截图还省略掉不少有价值的日志:
- embedding模型只花费2.38s就成功加载权重值,只使用1G内存(显存),这也是被称为小模型的原因,下面的reranker和语音模型也是如此;
- 暴露的端点,即Endpoint,或routes,有很多,不一一列举;
- 端口是8001;本地访问使用
http://0.0.0.0:8001/或http://localhost:8001,同一个局域网访问需要使用固定IP形式:http://192.168.4.134:8001/openapi.json; 192.168.4.123:63143是什么?
curl请求截图:


postman请求接口如下:

一行命令的可视化效果可能不太好,docker启动命令(多行):
测试
使用postman简单测试,POST请求,requestBody如下:
执行效果如下:

使用更加专业的py脚本来执行测试:
k8s
上面是使用docker方式启动模型,--restart=unless-stopped参数可以实现自动重启,但是重启(包括探针)机制不如k8s。
将上面的启动脚本扔给GPT,再经过调整,不难得到一个符合k8s或k3s的yaml文件:
reranker
与embedding经常一起出现的就是重排序,即reranker小模型。魔搭社区地址,一般用BAAI/bge-reranker-v2-m3
直接给出docker启动模型命令:
转化为k3s或k8s的yaml文件也很简单,将上面的embedding模型的yaml文件稍加改动即可。
语音
魔搭社区地址为iic/SenseVoiceSmall。启动SenseVoiceSmall模型的镜像不是vLLM,需要自己构建Docker镜像。如果转换为k3s yaml文件,则还需要将Docker镜像转化成crictl镜像。具体参考 docker、ctr、crictl命令简介与使用。
qwen2.5
部署的模型为DeepSeek-R1-Distill-Qwen-32B-AWQ,魔搭社区地址为Valdemardi/DeepSeek-R1-Distill-Qwen-32B-AWQ。
Docker启动模型的命令为:
Docker命令转换成k3s的yaml文件不难:
在使用k3s,需要注意的是:主节点已经crictl pull下载vLLM镜像,通过modelscope download下载过模型文件,在主节点执行k apply -f qwen2.5-worker.yaml文件,希望通过k8s调度到从节点部署;则从节点,也需要对应的镜像文件和crictl镜像。此时通过scp传输应该比下载来得快。
qwen3
Qwen3-30B-A3B
上面部署embedding、reranker、qwen2模型使用的vLLM镜像版本都是dustynv/vllm:0.7.4-r36.4.0-cu128-24.04,继续使用此版本部署qwen3模型,比如没有经过量化的Qwen3-30B-A3B,启动日志里有个报错:

升级使用的vLLM版本到dustynv/vllm:0.8.6-r36.4-cu128-24.04,即可成功部署。启动日志如下:

Qwen3-30B-A3B-GPTQ-Int4
如上截图所示,一个64G显存一体的Jetson Orin GPU卡,部署好Qwen3-30B-A3B模型,已经用去56G显存。那这张卡基本上就不能再部署其他服务或模型。
因此需要考虑部署量化版的Qwen3,在modelscope下载多个不同版本的模型,以及反复试错,解决问题后,成功部署Qwen3-30B-A3B-GPTQ-Int4。
给出yaml文件如下:
其中一个非常关键的配置是本地gptq_marlin.py文件挂载,替换vLLM默认的gptq_marlin.py文件。
其他
日志
vLLM部署Qwen3-30B-A3B-GPTQ-Int4模型的启动日志:
显存利用
其中有一段值得深扒:
注意到non_torch_memory使用的内存是负数。
GPT解读:
在vLLM的资源分配逻辑中,内存使用被分为几个部分:
|
内存类型 |
含义 |
|
model weights |
模型权重占用的显存(通常为FP16或INT8 |
|
non_torch_memory |
非PyTorch分配器管理的显存,如CUDA内存池、自定义内存等 |
|
PyTorch activation peak memory |
PyTorch激活函数使用的峰值内存(启用PyTorch backend) |
|
KV Cache |
用于缓存attention key/value的内存 |
这些加起来应该小于等于总的可用显存 × 利用率:total_gpu_memory * gpu_memory_utilization = model_weights + non_torch_memory + pytorch_activation + kv_cache
出现负数的可能原因:
- 数值溢出或精度误差:这些值可能是从GPU显存总量中减去其他已知项推导出来的;
- 估算方式不够严谨,或某些值过大,可能导致结果为负数。
原因:
- 模型太大:模型本身权重就很大,如Qwen3-30B;
- 配置不合理:设置较高的
max_num_seqs或max_seq_len,会导致KV Cache需求激增;加上一些激活内存开销,整体显存需求超过预留的60%,从而导致non_torch_memory被迫为负。
但是!!!
- 显存大小相同的两张Jetson Orin卡,都是64G;
- 都是Qwen3-30B-A3B-GPTQ-Int4模型;
--gpu-memory-utilization参数都是0.6。
一张卡是正数。另一张卡出现上述负数,第一次部署模型时,内存异常,触发pod重启,此时free -h查看剩余显存不够300M;

pod重启日志里该参数还是负数,等待pod启动成功,free -h查看剩余显存有1~2G。
杀掉进程,重新部署模型,还是负数。
作为TODO有待后续跟进的2个问题:
- 为啥是负数?
- 这个负数的绝对值大小有什么学问,也就是为啥第一次会触发pod异常重启?


所有评论(0)