基于Ray和vLLM实现大模型分布式推理

3/5/2025 Ray分布式计算vLLM推理加速NFS文件系统LLaMA-Factory大模型分布式推理

# 1. 技术选型概述

# 1.1 Ray分布式计算框架

Ray是 UC Berkeley riseLab针对机器学习领域开发的一种新的分布式计算框架,用于构建在任何规模下运行的分布式应用。其定位是一个通用的分布式编程框架,提供了统一的分布式底盘,能帮助用户将自己的程序快速分布式化。

Ray分布式计算框架

# 1.2 vLLM大模型推理框架

vLLM是一个大型语言模型推理加速工具,它通过优化内存管理、连续批处理、CUDA核心优化和分布式推理支持等技术手段,显著提高了大型语言模型的推理速度和效率。

vLLM吞吐量极高

注:在考虑并发量的服务端应用中,vLLM是目前最主流的大模型推理框架,它极大的提高了推理速度和吞吐量。而Ollama是给客户端用的,它的并发支持不行,且默认是4精度量化的模型,只适合个人自用。

# 2. 基础环境安装

# 2.1 准备服务器环境

# 2.1.1 部署环境说明

2台GPU服务器(每台 4×NVIDIA A16显卡,单卡16GB显存,总显存64GB),没有任何基础环境,从零开始安装部署。

网络地址:172.19.32.65、172.19.32.66,两台服务器之间的网络互通。

# 2.1.2 安装常用命令

$ apt-get install -y sudo                                     # 安装sudo
$ sudo apt-get update                                         # 更新apt-get
$ apt-get install iputils-ping -y                             # 安装ping
$ apt-get install -y wget                                     # 安装wget
$ apt-get install curl -y                                     # 安装curl
$ apt-get install xz-utils                                    # 安装xz
$ apt-get install p7zip-full                                  # 安装7z
$ apt-get install zip                                         # 安装zip
$ apt-get install tree                                        # 安装tree
$ apt-get install vim -y                                      # 安装vim
$ apt-get install lsof                                        # 安装lsof
$ apt-get install -y psmisc                                   # 安装ps
$ apt-get install screen                                      # 安装screen
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.1.3 下载模型权重

$ apt install git git-lfs
$ git lfs install
$ git clone https://hf-mirror.com/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B
1
2
3

# 2.2 安装显卡驱动与CUDA

# 2.2.1 安装CUDA环境

CUDA下载地址:https://developer.nvidia.com/cuda-toolkit-archive (opens new window),根据你的服务器情况进行选择,安装类型选择runfile (local),之后会自动给出安装命令。

CUDA官网给出安装命令

根据给出的命令进行下载安装,出来协议时直接输入accept,之后在CUDA Installer里选择Install。

$ wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda_12.1.0_530.30.02_linux.run 
$ sudo chmod u+x cuda_12.1.0_530.30.02_linux.run
$ sudo ./cuda_12.1.0_530.30.02_linux.run
1
2
3

安装CUDA环境

第一次安装失败,先查看cat /var/log/cuda-installer.log,再查看 cat /var/log/nvidia-installer.log,报错信息如下:

CUDA安装失败问题

解决办法是手动禁止Nouveau kernel driver的运行。

$ sudo vim /etc/modprobe.d/blacklist-nouveau.conf

在文件里写入:
blacklist nouveau
options nouveau modeset=0

$ sudo update-initramfs -u
$ sudo reboot
1
2
3
4
5
6
7
8

之后重新安装CUDA,这次就安装成功了。

$ sudo ./cuda_12.1.0_530.30.02_linux.run
1

CUDA安装成功

# 2.2.1 NVIDIA GPU资源查看

安装 nvidia-smi 及 nvidia-cuda-toolkit 工具

$ sudo apt update
$ sudo apt install nvidia-utils-520
$ sudo apt install nvidia-cuda-toolkit
1
2
3

使用 nvidia-smi 命令可以显示出GPU的所有基础信息。

$ nvidia-smi                 // 查询GPU详情
$ nvidia-smi -q              // 查询GPU型号
1
2

查看CUDA驱动版本:

$ nvcc --version
1

# 2.3 安装Docker并配置

# 2.3.1 安装Docker环境

$ apt install -y docker.io
$ cp ./docker-compose /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
$ systemctl enable docker
$ systemctl restart docker
1
2
3
4
5

# 2.3.2 配置Docker的GPU环境

$ cat ./gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
$ echo -e "deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://nvidia.github.io/libnvidia-container/stable/deb/\$(ARCH) /" > /etc/apt/sources.list.d/nvidia-container-toolkit.list
$ apt install nvidia-container-toolkit -y
1
2
3

# 2.3.3 配置Docker国内镜像源

$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
    	"https://docker.m.daocloud.io",
    	"https://docker.imgdb.de",
    	"https://docker-0.unsee.tech",
    	"https://docker.hlmirror.com",
    	"https://docker.1ms.run",
    	"https://func.ink",
    	"https://lispy.org",
    	"https://docker.xiaogenban1993.com"
    ]
}
EOF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 2.3.4 重启Docker使配置生效

$ sudo systemctl daemon-reload && sudo systemctl restart docker
1

# 2.4 搭建NFS文件系统

NFS(network file system)网络文件系统工具,通过网络使不同机器或者操作系统之间分享部分文件,用于宿主机和目标机之间的文件共享。使用该方式需要管理员权限,服务端配置好后,客户端不需要认证登录就可以挂载。

文件服务器(被挂载机):172.19.32.65    // 实际存储文件的地方
操作服务器(挂载机):172.19.32.66     // 使用文件的地方(实际不存储在这里)
1
2

# 2.4.1 安装NFS环境

安装 NFS(两台机器都需要安装)并设置开机自启

$ sudo apt-get install nfs-kernel-server -y     // 安装 NFS 服务
$ systemctl status nfs-kernel-server.service    // 查看NFS服务是否启动
$ systemctl enable nfs-kernel-server.service    // 设置NFS主程序开机启动
1
2
3

# 2.4.2 在被挂载机上配置

Step2:在文件服务器(被挂载机)上新建目录,配置权限,配置挂载

$ mkdir -p /deepseek && chmod 777 -R /deepseek
$ vim /etc/exports
1
2

编辑需要共享的目录和允许访问的服务器(*为不限制IP,不建议这么做,但如果不想限制IP就把如下配置的192.168.1.200换成*即可)及权限,内容如下:

/deepseek *(rw,sync,no_root_squash)
1

注:如果服务器的端口大于1024,则还需要加上insecure,如果未加 insecure,下一步挂载时会报错mount.nfs: access denied by server while mounting

/deepseek *(insecure,rw,sync,no_root_squash)  
1

重启文件服务器(被挂载机)NFS服务。

$ sudo /etc/init.d/nfs-kernel-server restart
1

另注:如果挂载后创建文件出现mount.nfs: Read-only file system的错误,是/etc/exports的配置有问题(例如IP与权限的那个括号之间应该没有空格,请查看是不是加了空格导致的)。

# 2.4.3 在挂载机上配置

操作服务器(挂载机)新建目录,配置挂载

$ mkdir /deepseek
$ sudo mount 172.19.32.65:/deepseek /deepseek
$ mount                          // 显示当前系统已经挂载的设备及挂载点
$ cd /deepseek && touch test.txt // 创建测试⽂件,去⽂件服务器(被挂载机)查看⽂件是否存在
$ cd /deepseek && rm -f test.txt // 删除测试⽂件
1
2
3
4
5

使用 umount 卸载挂载

 $ sudo umount 172.19.32.65:/deepseek /deepseek
1

注意:如果出现 umount.nfs: XXX: device is busy 错误,可使用以下方式强制卸载挂载

$ sudo fuser –m –v /storage
$ kill -9 [pid]
$ sudo umount –lf 172.19.32.65:/deepseek /deepseek
1
2
3

# 2.4.4 设置开机自动挂载

$ vim /etc/rc.local  // 写入如下配置
sudo mount 172.19.32.65:/deepseek /deepseek
1
2

# 3. 推理服务部署

# 3.1 将两台机器连接上Ray集群

# 3.1.1 拉取vLLM的镜像

两台机器拉取vLLM最新的Docker镜像,此时最新的vLLM是v0.7.2。

$ docker pull vllm/vllm-openai                  // 官方源
$ docker pull docker.1ms.run/vllm/vllm-openai   // 国内受限的话,可以用这个镜像源
1
2

# 3.1.2 编写集群启动脚本

分别给两个机器编写集群启动脚本,CUDA_VISIBLE_DEVICES按照当前机器的空余显卡来写。

#!/bin/bash

if [ $# -lt 2 ]; then
    echo "Usage: $0 head_node_address --head|--worker [additional_args...]"
    exit 1
fi

HEAD_NODE_ADDRESS="$1"
NODE_TYPE="$2"
shift 2

ADDITIONAL_ARGS=("$@")

if [ "${NODE_TYPE}" != "--head" ] && [ "${NODE_TYPE}" != "--worker" ]; then
    echo "Error: Node type must be --head or --worker"
    exit 1
fi

cleanup() {
    if [ -e /var/lib/docker/containers/vllm ]; then
        docker stop vllm
        docker rm vllm
    fi
}
trap cleanup EXIT

RAY_START_CMD="ray start --block"
if [ "${NODE_TYPE}" == "--head" ]; then
    RAY_START_CMD+=" --head --port=6379"
else
    RAY_START_CMD+=" --address=${HEAD_NODE_ADDRESS}:6379"
fi

docker run -itd \
    --privileged \
    --entrypoint /bin/bash \
    --network host \
    --name vllm \
    --shm-size 10000000g \
    --gpus all \
    -v /deepseek/DeepSeek-R1-Distill-Qwen-32B/:/mnt \
    "${ADDITIONAL_ARGS[@]}" \
    -e CUDA_VISIBLE_DEVICES=0,1,2,3 \
    docker.1ms.run/vllm/vllm-openai:latest \
    -c "${RAY_START_CMD}
    --restart=always\"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

关键参数解释:

-v /DeepSeek-R1-Distill-Qwen-32B/:/mnt   # 将DeepSeek-R1-Distill-Qwen-32B挂载到/mnt目录
-e CUDA_VISIBLE_DEVICES=0,1,2,3          # 指定显卡
1
2

# 3.1.3 启动Ray集群节点

随便选一台服务器作为head节点,另一台作为worker节点。

head节点容器启动

$ bash run_cluster_head.sh 172.19.32.65 --head
1

worker节点容器启动

$ bash run_cluster_worker.sh 172.19.32.65 --worker
1

从任意服务器进入容器内,检查是否连接上了Ray集群。

$ docker exec -it vllm /bin/bash
$ ray status
1
2

发现两个节点都在,证明Ray启动脚本没问题,停止删除两个Docker容器。

检查Ray集群的连接情况

# 3.2 LLaMA-Factory部署API服务

# 3.2.1 修改源码的初始化参数

下载 LLaMA-Factory 项目的源码。

$ cd /deepseek
$ git clone https://github.com/hiyouga/LLaMA-Factory.git
1
2

需要对 vllm_engine.py (opens new window) 里AsyncLLMEngine的初始化参数做一下更改。

原来是这样:

engine_args = {
            "model": model_args.model_name_or_path,
            "trust_remote_code": model_args.trust_remote_code,
            "download_dir": model_args.cache_dir,
            "dtype": model_args.infer_dtype,
            "max_model_len": model_args.vllm_maxlen,
            "tensor_parallel_size": get_device_count() or 1,
            "gpu_memory_utilization": model_args.vllm_gpu_util,
            "disable_log_stats": True,
            "disable_log_requests": True,
            "enforce_eager": model_args.vllm_enforce_eager,
            "enable_lora": model_args.adapter_name_or_path is not None,
            "max_lora_rank": model_args.vllm_max_lora_rank,
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

需要把tensor_parallel_size手动改为多机使用的卡数。

engine_args = {
            "model": model_args.model_name_or_path,
            "trust_remote_code": model_args.trust_remote_code,
            "download_dir": model_args.cache_dir,
            "dtype": model_args.infer_dtype,
            "max_model_len": model_args.vllm_maxlen,
            "tensor_parallel_size": 8,  # 改了这里
            "gpu_memory_utilization": model_args.vllm_gpu_util,
            "disable_log_stats": True,
            "disable_log_requests": True,
            "enforce_eager": model_args.vllm_enforce_eager,
            "enable_lora": model_args.adapter_name_or_path is not None,
            "max_lora_rank": model_args.vllm_max_lora_rank,
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.2.2 修改集群启动脚本

需要将LLaMA-Factory项目挂载进容器,并安装相关依赖。

#!/bin/bash

if [ $# -lt 2 ]; then
    echo "Usage: $0 head_node_address --head|--worker [additional_args...]"
    exit 1
fi

HEAD_NODE_ADDRESS="$1"
NODE_TYPE="$2"
shift 2

ADDITIONAL_ARGS=("$@")

if [ "${NODE_TYPE}" != "--head" ] && [ "${NODE_TYPE}" != "--worker" ]; then
    echo "Error: Node type must be --head or --worker"
    exit 1
fi

cleanup() {
    if [ -e /var/lib/docker/containers/vllm ]; then
        docker stop vllm
        docker rm vllm
    fi
}
trap cleanup EXIT

RAY_START_CMD="ray start --block"
if [ "${NODE_TYPE}" == "--head" ]; then
    RAY_START_CMD+=" --head --port=6379"
else
    RAY_START_CMD+=" --address=${HEAD_NODE_ADDRESS}:6379"
fi

FULL_CMD+="pip install datasets peft trl sse_starlette -i https://pypi.tuna.tsinghua.edu.cn/simple && ${RAY_START_CMD}"

docker run -itd \
    --privileged \
    --entrypoint /bin/bash \
    --network host \
    --name vllm \
    --shm-size 10000000g \
    --gpus all \
    -v /deepseek/DeepSeek-R1-Distill-Qwen-32B/:/mnt/ \
    -v /deepseek/LLaMA-Factory/:/app \
    "${ADDITIONAL_ARGS[@]}" \
    -e CUDA_VISIBLE_DEVICES=0,1,2,3 \
    docker.1ms.run/vllm/vllm-openai:latest \
    -c "${FULL_CMD}"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 3.2.3 启动大模型推理服务

head节点容器启动

$ bash run_cluster_head.sh 172.19.32.65 --head
1

worker节点容器启动

$ screen -S deepseek
$ bash run_cluster_worker.sh 172.19.32.65 --worker
$ VLLM_WORKER_MULTIPROC_METHOD=spawn \
CUDA_VISIBLE_DEVICES=0,1,2,3 \
DISABLE_VERSION_CHECK=1 \
python3 /app/src/api.py \
    --model_name_or_path /mnt/ \
    --template deepseek3 \
    --infer_backend vllm \
    --vllm_enforce_eager True \
    --vllm_gpu_util 0.9 \
    --vllm_maxlen 60000 \
    --max_new_tokens 32768
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3.2.4 验证推理服务是否正常

使用如下命令进行验证,可以得到符合预期的输出,部署成功。

$ curl --location --request POST 'http://172.19.32.66:8000/v1/chat/completions' \
--header 'Content-Type: application/json' \
--data-raw '{
    "model": "DeepSeek-R1-Distill-Qwen-32B", 
    "messages": [ 
        {
            "role": "user", 
            "content": "树上有四只鸟,开枪打死一只,还剩几只?"
        }
    ],
    "temperature": 0.6,
    "stream": true
}'
1
2
3
4
5
6
7
8
9
10
11
12
13

# 4. 参考资料

[1] deepseek r1满血版本部署 from 微信公众号 (opens new window)

[2] 分布式推理和服务 from vLLM官方文档 (opens new window)

[3] 尝试基于vLLM+Ray多机部署满血DeepSeek-R1 from 知乎 (opens new window)

[4] Ray+vLLM+LLaMA-Factory多机部署大模型 from 知乎 (opens new window)

[5] Ray 分布式计算框架介绍 from 知乎 (opens new window)

[6] 基于 Ray 的大规模离线推理 from 稀土掘金 (opens new window)

Last Updated: 3/8/2025, 11:21:30 AM