ollama和vllm 的对比

这块对比网上都很多资料了,

这边使用上简单感觉就是ollama很方便部署,占用资料更少,但后续性能会差点,各选项也不一样.

ollama安装和使用和docker很像,就不赘述了,这里是看vllm的安装

硬件情况介绍

3070 8G显存

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.133.20             Driver Version: 570.133.20     CUDA Version: 12.8     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 3070        Off |   00000000:08:00.0  On |                  N/A |
| 30%   38C    P8             16W /  240W |    5225MiB /   8192MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A          346687      C   ...niconda3/envs/vllm/bin/python       5200MiB |
+-----------------------------------------------------------------------------------------+

安装vllm

vllm的安装, 要选用gpu版本

不同平台的安装说明可以参考官网

https://docs.vllm.ai/en/latest/getting_started/installation/index.html

建议新开一个环境来执行pip, 如conda activate vllm_env

这里用 cuda 128 版本

pip install vllm --extra-index-url https://download.pytorch.org/whl/cu128

pip list 关键的一些版本号: 

torch                             2.7.0+cu128
torchaudio                        2.7.0+cu128
torchvision                       0.22.0+cu128
vllm                              0.9.2


启动命令

vllm有很多启动方式,这边采用python -m vllm.entrypoints.openai.api_server

python -m vllm.entrypoints.openai.api_server \
  --model /home/xxx/data/hf_models/Qwen3-8B \
  --served-model-name DQwen3-8B \
  --gpu-memory-utilization 0.5 \
  --host 0.0.0.0 \
  --port 8003 \
  --max-num-seqs 2 \
  --enable-chunked-prefill \
  --trust-remote-code \
  --max-model-len 1024
  

llm()加载模型时可以使用modelscope环境 export VLLM_USE_MODELSCOPE=True

命令的参数很多, 这边简单说明:

model 加载的模型,可以用本地,是huggingface下载的
served-model-name 名称,用于后续外围访问时用
gpu-memory-utilization  只预分配 50 % 的 GPU 显存做 KV Cache/权重缓存,避免一次性占满整卡。 显存不太够时用
--max-num-seqs 2 同一时刻最多并发 2 条序列(含 prompt 与正在生成的 token)。数值越小,显存峰值越低。
--enable-chunked-prefill  把长 prompt 切成小块逐步预填充,减少一次性显存峰值,对长文本尤其有用。
--max-model-len 1024  把模型的最大上下文长度 硬截断到 1024 tokens。超过此长度的输入会被截断或拒绝。

如果加载 Qwen3-8B直接out of memory了,使用1.5B都还是内存不够,但ollama是可以执行8B的,

从huggingface 下载的和ollama的库的大小也是不一样的, 这是因为ollama对挂在他们上在的模型做了一些处理,如4BIT的量化,所以这边要执行也要对模型量化一下(quantization)

实测在3070,做8B还是有点勉强,所以这里使用Qwen3-4B

显存占用太高,量化4Bit

  • 量化有几种方式,这边试了下,用bitsandbytes
# 把精度调下来,给vllm 加载(官方例子)
# https://huggingface.co/docs/bitsandbytes/installation#cuda-pip
# https://huggingface.co/docs/transformers/v4.53.3/en/quantization/bitsandbytes?bnb=4-bit#bitsandbytes

model_name = "Qwen3-4B"
model_path = f"/home/xxx/data/hf_models/{model_name}"
quant_path = f"/home/xxx/data/hf_models/{model_name}-quantizated"

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)

model = AutoModelForCausalLM.from_pretrained(
    model_path, 
    device_map="auto",
    quantization_config=quantization_config
)

model.save_pretrained(quant_path)
print(f'done--------------------{quant_path}')


  • 另外awq库也可以,不过这边不成功, 应该是版本不太对 ,
# 把精度调下来,给vllm 加载(官方例子)
# https://docs.vllm.ai/en/latest/features/quantization/auto_awq.html
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

ultrachat_200k_path = "/home/xxx/data/hf_datasets/ultrachat_200k"
model_path = "/home/xxx/data/hf_models/Qwen1.5-1.8B-Chat"
quant_path = "/home/xxx/data/hf_models/model-quantized-1"

# model_path = 'mistralai/Mistral-7B-Instruct-v0.2'
# quant_path = 'mistral-instruct-v0.2-awq'
quant_config = { "zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM" }

# Load model
model = AutoAWQForCausalLM.from_pretrained(
    model_path, **{"low_cpu_mem_usage": True, "use_cache": False}
)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# Quantize
model.quantize(tokenizer, quant_config=quant_config)

# Save quantized model
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)

print(f'Model is quantized and saved at "{quant_path}"')

启动与测试情况

python -m vllm.entrypoints.openai.api_server \
  --model /home/xxx/data/hf_models/Qwen3-4B-quantized  \
  --served-model-name DQwen3-4B-quantized \
  --gpu-memory-utilization 0.5 \
  --host 0.0.0.0 \
  --port 8003 \
  --max-num-seqs 2 \
  --enable-chunked-prefill \
  --trust-remote-code \
  --max-model-len 1024
  

如果直接启动抛错可能看不到错误栈,把日志级别改一下再启动
export VLLM_LOGGING_LEVEL=DEBUG

测试:


print(1111)
from openai import OpenAI

# client = OpenAI(
#     base_url="http://localhost:11434/v1",  # 关键:指向 Ollama
#     api_key="ollama"                       # 随意填,Ollama 不校验
# )

client = OpenAI(
    base_url="http://localhost:8003/v1",  # 关键:指向 vllm 的端口
    api_key="ollama"                       # 随意填
)

resp = client.chat.completions.create(
    # model="deepseek-r1:7b",                       # 本地已 pull 的模型名
    model="DQwen3-4B-awq",                       # 本地已 pull 的模型名 (vllm指定的served-model-name)
    messages=[
        {"role": "system", "content": "你是一个科学家,用一个简短的话语回答问题。"},
        {"role": "user",   "content": "天空为什么是蓝色的?用简短的话回答。"}
    ],
    temperature=0.7,
    max_tokens=512
)

print(resp.choices[0].message.content)


返回

1111
<think>
好的,用户问天空为什么是蓝色的。我需要简短回答,所以得抓住关键点。首先,瑞利散射,对吧?太阳光由不同颜色的光组成,波长短的蓝光散射更多。大气中的分子会散射这些光,导致我们看到蓝色。不过,可能需要更简洁的表达。

用户可能想了解基本原理,不需要太深入。可能需要提到散射和颜色。比如,"因为瑞利散射,蓝光被散射得更多,所以天空呈现蓝色。" 但可能需要更简练。或者,"太阳光中的蓝光被大气分子散射,使天空呈现蓝色。" 这样更直接。

检查有没有更简短的表达。比如,"蓝光散射多,所以天空是蓝的。" 但可能不够准确。需要确保术语正确。瑞利散射是关键,但用户可能不需要知道术语。所以可能需要用更通俗的说法。

可能用户是学生或者普通爱好者,需要基础解释。所以,正确的科学解释是瑞利散射导致蓝光散射,所以天空是蓝的。但可能需要更简短,比如"因蓝光散射强,天空呈蓝色。" 或者"蓝光被散射,所以天空是蓝的。"

确定答案是否正确。是的,正确。所以最终回答应该是这个。
</think>

因蓝光散射强,天空呈蓝色。

一些进程简单情况

================= 进程 346687 运行指标 =================
进程名       : python
启动时间     : 2025-07-24 11:49:03
完整命令     : /home/xxx/miniconda3/envs/vllm/bin/python -c from multiprocessing.spawn import spawn_mai
n; spawn_main(tracker_fd=36, pipe_handle=38) --multiprocessing-fork
-----------------------------------------------------
物理内存(RSS) : 2884.8 MB
虚拟内存(VSZ) : 19977.9 MB
Swap 占用     : 0.0 MB
OOM Score     : 774
显存          : 5200MiB 
-----------------------------------------------------
已打开 FD 数 : 92
线程数       : 63
子进程数     : 0
-----------------------------------------------------
UDP 套接字数 : 7
RX 总字节    : 5.36829e+10
TX 总字节    : 2.29815e+10
-----------------------------------------------------
cgroup      : 0::/user.slice/user-1000.slice/session-338.scope
pid namespace: pid:[4026531836]
pid:[4026531836]
net namespace: net:[4026531840]
=====================================================

linux limit 的问题

运行久以后可能会出现 limit 的问题,fd开不了了,这里可以配置下limit 即进程可开的fd数

gradio也遇到过:

The global thread pool has not been initialized.: ThreadPoolBuildError { kind: IOError(Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }) }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
查看限制

ulimit -n // 查看限制open file

查看当前用户的 soft/hard nofile 限制

ulimit -Sn # soft nofile
ulimit -Hn # hard nofile

查看系统全局默认值(所有用户)

cat /proc/sys/fs/file-max # 系统总 FD 上限
cat /proc/sys/fs/nr_open # 单个进程最大 FD 上限

对应的配置

(1) /security/limits.conf // 对应的全局配置
加上限制:

open files (-n)

针对所有用户(不推荐)

* soft nofile 65536
* hard nofile 65536

针对某个用户

xxx soft nofile 65536  # 默认是1024
xxx hard nofile 65536

(2) 如果是systemctl 配置的

编辑服务文件

sudo nano /etc/systemd/system/vllm-api.service

添加以下配置

[Service]
LimitNOFILE=65535
然后执行:
sudo systemctl daemon-reload
sudo systemctl restart vllm-api

(3) 如果是supervisor, supervisor里有对应的配置

(4) 如果想临时在当前会话设置一下
ulimit -n 65535 # 将 soft nofile 改为 65535

查看当前进程的fd情况

# 查看当前进程的 FD 限制
cat /proc/<PID>/limits | grep "Max open files"

# 统计进程当前使用的 FD 数量
ls -l /proc/<PID>/fd | wc -l
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐