专栏
vllm简介
- vLLM 是一个高性能、易扩展的大模型推理框架,专为生产环境中的大规模语言模型部署而设计。它通过创新的 PagedAttention 内存管理技术,显著提升了 GPU 的显存利用率,同时支持分布式推理,能够高效利用多机多卡资源。无论是低延迟、高吞吐的在线服务,还是资源受限的边缘部署场景,vLLM 都能提供卓越的性能表现。其简洁的 API 设计和灵活的部署方式,使得开发者能够快速集成并优化大模型推理任务,是私有化部署中不可或缺的利器。
- vllm官方中文文档
vllm实践
前置安装,如果conda和nvidia驱动都安装好了可跳过这步
- 查看没有激活conda环境下python版本
python3 --version
我的是Python 3.10.12
安装nvidia驱动
- 这里注意如果需要deepspeed分布式环境后面还需要升级版本,当前配置可用于vllm分布式部署
- 先禁用nouveau
echo -e "blacklist nouveau\noptions nouveau modeset=0" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
sudo update-initramfs -u
sudo reboot
- 无输出就说明成功了
lsmod | grep nouveau
- 执行如下命令
wget https://cn.download.nvidia.com/XFree86/Linux-x86_64/535.113.01/NVIDIA-Linux-x86_64-535.113.01.run -O nvidia.run
./nvidia.run
reboot
- nvidia-smi显示如下就成功了
- 安装工具包, 然后执行看版本的命令能输出就成功了
apt install nvidia-cuda-toolkit
nvcc --version
安装conda
- 安装依赖包
apt install libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6
- 下载anaconda, bash之后然后一路回车
wget https://repo.anaconda.com/archive/Anaconda3-2022.10-Linux-x86_64.sh
chmod +x Anaconda3-2022.10-Linux-x86_64.sh
bash Anaconda3-2022.10-Linux-x86_64.sh
- 加环境变量
export PATH=~/anaconda3/bin:$PATH
source ~/anaconda3/bin/activate
source ~/.bashrc
- 测试下
conda list
vllm安装
- 快速安装vllm
conda create -n vllm python=3.10 -y
conda activate vllm
pip install vllm
- 或者使用源码安装
git clone https://github.com/vllm/vllm.git
cd vllm
pip install -e .
vllm实践
下载模型
export HF_ENDPOINT=https://hf-mirror.com
pip install modelscope
- 使用modelscope下载并缓存到/usr/local,模型地址可以改成你想要下载的
import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import os
from modelscope.hub.api import HubApi
api = HubApi()
# 有的地方需要,key在 modelscope.cn/models 右上角个人那边
# api.login('xxx你的账号对应的key')
model_dir = snapshot_download('Qwen/Qwen2.5-72B-Instruct-AWQ', cache_dir='/usr/local',revision='master')
print(model_dir)
使用vllm推理
- 这边使用的是vllm的openai进行推理, 用的是Qwen2.5-72B-Instruct-AWQ,两张A10即可跑起来,如果跑别的模型可以改改, 注意这里显存有限,又要跑那么大模型,我就把模型tokenizer_config.json的max-model-len从几万改到6666了,后台启动, --model改成你自己存放大模型的地址,max-model-len看个人需求,我的conda vllm个人环境是设置的vllm
conda activate vllm
export HF_ENDPOINT=https://hf-mirror.com
nohup python -m vllm.entrypoints.openai.api_server \
--model /root/.cache/huggingface/hub/models/Qwen/Qwen2-72B-Instruct-AWQ/snapshots/26975fbe12cda45e38c0b99da62f1a7deab1bf25 \
--tensor-parallel-size 2 \
--host 0.0.0.0 \
--port 5000 \
--served-model-name Qwen/Qwen-72B-AWQ \
--cpu-offload-gb 5.0 \
--quantization awq \
--max-model-len 6666 \
--gpu-memory-utilization 0.9 \
& >> out1.log 2>&1
应用端读取vllm后台启动
- 因为有些python版本不太支持直接使用openai, 这边使用了更通用的http请求的方式, 应用层代码如下, 注意xxxx改成你自己客户端的ip
import datetime
import json
import requests
class Qwen:
def __init__(self, msg, model=''):
self.msg = msg
self.model = model
def get_tags_map_res(self):
if self.model == '':
self.model = 'Qwen/Qwen-72B-AWQ'
# xxxx换成你的ip
url = f"http://xxxx:5000/v1/chat/completions"
system = """你是tomcat"""
content = '''
- Data:
{msg}
'''
return self.send_msg_and_get_resp(content, system, url)
def send_msg_and_get_resp(self, content, system, url):
headers = {
'Content-Type': 'application/json'
}
messages = [{'role': 'system', 'content': system},
{"role": "user", "content": content.replace('{msg}', self.msg)}]
data = {
"model": self.model,
"messages": messages
}
response = requests.post(url, headers=headers,
data=json.dumps(data),
timeout=(30.0, 360.0))
return json.loads(response.text)['choices'][0]['message']['content']
def parse_mtr_data(self):
pass
if __name__ == '__main__':
t1 = datetime.datetime.now()
print("now————", t1)
content = """你好呀tomcat"""
model = Qwen(content)
res = model.get_tags_map_res()
print("Vllm's response:")
print(res)
print('____________________________')
end = datetime.datetime.now()
print('res ,cost:+++++++++++++++++++++++++++++++', str(end - t1))
- 响应如下
分布式vllm部署
- 目前参考官方文档多机多卡使用docker部署
- docker安装
apt install docker.io
- 通过docker拉取最新vllm镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/vllm/vllm-openai:latest
- docker并不能直接看见宿主机的gpu所以要执行下面命令, 作者的第二台机器是删掉了之前有问题的conda activate xxx环境重新install才成功的
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo apt-get install -y nvidia-docker2
systemctl restart docker
- 下载或者复制官方文档提到的集群脚本多节点推理和服务
- 我这边下载下来要执行下不然会报格式错误,如果你们没报格式错误就不会执行下面格式化命令
dos2unix run_cluster.sh
- 然后vim run_cluster.sh里面的docker run加下-p 5000:5000
- 然后两台机器分别执行下面命令,master_ip_xxx请换成你的主节点, -v是挂载节点你可以换成你自己的,ens3是我的网卡地址。注意两台机器的大模型目录都要保持一致
# 启动主节点命令
bash run_cluster.sh \
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/vllm/vllm-openai \
master_ip_xxx \
--head /root/.cache/huggingface/hub \
-v /root/.cache/huggingface/hub/:/model/ \
-e GLOO_SOCKET_IFNAME=ens3 \
-e NCCL_SOCKET_IFNAME=ens3
# 启动工作节点命令
bash run_cluster.sh \
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/vllm/vllm-openai \
master_ip_xxx \
--worker /root/.cache/huggingface/hub \
-v /root/.cache/huggingface/hub/:/model/ \
-e GLOO_SOCKET_IFNAME=ens3 \
-e NCCL_SOCKET_IFNAME=ens3
- 通过下面命令查看ray集群的状态, xxx是docker ps -a对应的id
docker exec -it xxx /bin/sh
ray statys
- 能看到多个节点说明成功了
- 然后我这边在备集群执行下面启动vllm命令, 这样就能在两台机器上看到显存被占用
python3 -m vllm.entrypoints.openai.api_server \
--model /model/models/Qwen/Qwen2-72B-Instruct-AWQ/snapshots/26975fbe12cda45e38c0b99da62f1a7deab1bf25 \
--pipeline-parallel-size 2 \
--tensor-parallel-size 1 \
--host 0.0.0.0 \
--port 5000 \
--served-model-name Qwen/Qwen-72B-AWQ \
--enforce-eager \
--cpu-offload-gb 3.0 \
--quantization awq \
--max-model-len 3000 \
--gpu-memory-utilization 1.0
vllm以及大模型采样策略说明
- vllm openai启动后,客户端可以传递多个采样参数,下面解释下各个参数含义
1. n 参数
-
定义:
n
参数用于指定在一次生成请求中,模型应返回多少个完全独立的生成序列。这意味着在同一组输入下,模型会生成n
个不同的结果。每个生成序列可以独立使用不同的采样策略(如贪心搜索、随机采样、Top-k、Top-p 等)。 -
优点:
- 多样性:提供多种生成结果,用户可以从多个候选中选择最合适的。
- 鲁棒性:增强生成结果的可靠性,用户可以根据需求筛选最佳输出。
-
缺点:
- 计算开销:由于需要生成多个完整的候选序列,计算资源消耗较大。
-
流程:同时启动多个生成过程,每个过程生成一个独立的序列。
-
实现:可以通过多线程、多进程或在 GPU 上并行处理多个生成任务。每个任务可以应用不同的随机种子或采样策略。
-
应用场景:在对话系统中,提供多个回答选项,供用户选择或系统进一步优化。
2. Top-k Sampling 机制
-
定义:在每个生成步骤中,从模型的概率分布中选择前
k
个最有可能的 token。这些 token 是当前时间步中概率最高的候选。然后,从这k
个 token 中随机采样一个作为下一个生成的 token。 -
优点:
- 限制采样范围:减少选择低概率或不合理 token 的风险。
- 多样性:在较高概率范围内增加生成结果的多样性。
-
缺点:
- k 值选择:选择合适的
k
值至关重要。k
值过小会限制多样性,而k
值过大可能导致选择不合理的 token。
- k 值选择:选择合适的
3. Temperature 参数
-
定义:
temperature
参数用于调整模型输出的概率分布。当temperature = 1.0
时,模型输出的概率分布保持不变,这是默认设置。此时,Softmax 函数将原始的 logits 直接转换为概率分布,反映模型对下一个 token 的信心水平。 -
作用机制:
-
Softmax 函数:在自注意力层和 MLP 之后,Softmax 函数将模型输出的 logits 转换为概率分布。
temperature
的作用可以简单理解为对 logits 进行缩放。 -
温度值影响:
- 当
temperature < 1.0
时,logits 的数值差异会被放大,导致高概率 token 的概率更高,低概率 token 的概率更低。在 Top-k 或 Top-p 采样中,差异小的 token 会随机选择,而差异大的 token 会倾向于贪心选择。 - 当
temperature = 1.0
时,logits 的数值保持不变,概率分布直接从模型的 logits 中计算得出。
- 当
-
4. Beam Search
-
定义:Beam Search 是一种系统地探索解空间的搜索算法,用于在序列生成中找到高概率的输出。算法在每个时间步维持多个候选序列(称为 beam),并扩展这些序列至下一个时间步。每个时间步,算法保留概率最高的
b
个序列(b
是 beam width),并丢弃其余的。 -
优点:
- 全局最优解:相比贪心搜索,Beam Search 能够探索更多路径,更有可能找到全局最优解。
- 高质量输出:通常用于需要高质量和连贯性输出的任务,如机器翻译。
-
缺点:
- 计算复杂度:由于需要在每个时间步追踪多个候选序列,计算开销较大。
- 多样性不足:倾向于选择高概率路径,可能导致输出结果相似。
-
应用场景:适合需要生成高质量、连贯输出的任务,如机器翻译、摘要生成等。相比 Top-k 和 Top-p,Beam Search 的输出更加连贯。
5. 贪心搜索(Top-k 设置为 1)
-
定义:在每个时间步,选择概率最高的 token 作为输出。
-
优点:
- 简单高效:计算效率高,实现简单。
-
缺点:
- 局部最优:可能错过全局最优解,因为它不考虑未来的解码路径。