Omni代码分析 ‐‐ Global Proxy - MozhiJiawei/Personal-Wiki GitHub Wiki

说明:
- 整体支持xPyD部署模式,y当前仅支持1,多个主机组成一台Decode模型实例,对外提供服务
- 910C上,一台服务器有8卡16die,可以满足一个P节点的部署
- Global_Proxy与Prefill首节点共部署
代码中有两个docker_file以及相应的构建脚本。

📦 容器镜像层次:
├─ 🏠 基础镜像: registry-cbu.huawei.com/omni_infer_v1/base_py311
│ ├─ openEuler 22.03-LTS (ARM64)
│ ├─ Python 3.11.4 (源码编译)
│ ├─ 华为昇腾CANN 7.7套件
│ ├─ 科学计算包(numpy, scipy, torch等)
│ └─ 系统依赖和开发工具
│
└─ 🚀 应用镜像: registry-cbu.huawei.com/omni_infer_v1/omni_infer
├─ 基于上述基础镜像
├─ vLLM推理引擎(昇腾优化版)
├─ OmniInfer核心代码
├─ Nginx全局代理(7个负载均衡模块)
└─ PyTorch-NPU 2.5.1
操作系统基础:
FROM registry-cbu.huawei.com/openeuler/openeuler-aarch64:22.03-lts
系统包依赖:
- 开发工具: git, vim, wget, Development Tools
- 网络工具: net-tools, openssl-devel
- 系统库: bzip2-devel, libffi-devel, sqlite-devel, pcre, libuuid-devel
- 硬件相关: pciutils, kmod, systemd, systemd-udev
Python环境:
- Python 3.11.4: 从源码编译安装,启用优化选项
- 基础Python包: pip, setuptools, wheel
华为昇腾CANN套件 (完整HPC高性能计算包):
-
CANN-compiler*.run
- 编译器组件 -
CANN-toolkit*.run
- 工具包 -
CANN-runtime*.run
- 运行时环境 -
CANN-opp*.run
- 算子包 -
CANN-hccl*.run
- 集合通信库 -
CANN-aoe*.run
- 自动算子优化 -
CANN-ncs*.run
- 网络控制服务 -
CANN-fwkplugin*.run
- 框架插件 -
Ascend-aicpu*.run
- AI CPU运行时 -
Ascend910_93-opp_kernel*.run
- 910芯片算子内核 -
Ascend-cann-nnal_8.1.RC1
- 神经网络加速库
Python科学计算依赖:
# 核心科学计算包
numpy<2.0.0, scipy, sympy, numba
# 深度学习基础
attrs, decorator, cffi, pyyaml, protobuf
# 分布式和服务
ray, tornado, requests, absl-py
# 工具包
psutil, pathlib2, setuptools_scm, typing_extensions
基础环境:
ARG BASE_IMAGE
FROM ${BASE_IMAGE} # 继承上面的基础镜像
深度学习框架:
- PyTorch 2.5.1: 主要深度学习框架
- torch-npu: 华为NPU适配的PyTorch版本
- ml-dtypes: 机器学习数据类型支持
推理引擎核心:
- vLLM: 高性能大语言模型推理引擎 (卸载原版,安装定制版)
- vllm_ascend: 华为昇腾适配的vLLM版本
- compressed-tensors==0.9.4: 模型压缩和量化支持
OmniInfer核心组件:
- omni_infer源码: 项目主要代码,以开发模式安装
-
推理引擎:
bash bash_install_code.sh
安装推理引擎
容器实例规格:
Prefill容器:
命名: omni_infer_prefill_p{node_rank}
资源限制:
NPU: 0-16 NPU卡专用
内存: 500GB共享内存
CPU: 16-32核心
网络: host模式(高性能)
存储挂载:
- 模型目录: /data/models (只读)
- 日志目录: /var/log/omni_infer
- 配置目录: /etc/omni_infer
Decode容器:
命名: omni_infer_decode_d{node_rank}
资源限制:
NPU: 0-16卡专用
内存: 500GB共享内存
CPU: 8-16核心
网络: host模式(高性能)
存储挂载: (同Prefill)
Proxy容器:
命名: omni_infer_proxy_c{node_rank}
资源限制:
CPU: 4-8核心
内存: 8-16GB
网络: host模式
端口映射: proxy_port + node_rank
容器启动脚本:
docker run -it --shm-size=500g \
# 环境变量设置
-e OMNI_INFER_SCRIPTS=$OMNI_INFER_SCRIPTS \
-e RANKTABLE_SAVE_PATH={{ ranktable_save_path }} \
-e MODEL_PATH=$MODEL_PATH \
-e LOG_PATH=$LOG_PATH \
# 网络和权限设置
--net=host \
--privileged=true \
-u root \
-w /data \
# NPU设备挂载
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--entrypoint=bash \
# 挂载目录配置
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /usr/local/sbin:/usr/local/sbin \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /usr/bin/hccn_tool:/usr/bin/hccn_tool \
-v /tmp:/tmp \
-v /data:/data \
-v $MODEL_PATH:$MODEL_PATH \
-v $LOG_PATH:$LOG_PATH \
-v $SCRIPTS_PATH:$SCRIPTS_PATH \
-v $CODE_PATH:$CODE_PATH \
-v {{ ranktable_save_path }}:{{ ranktable_save_path }} \
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \
挂载目录详细信息:
- Ascend NPU 相关目录
宿主机路径 | 容器内路径 | 用途 |
---|---|---|
/usr/local/Ascend/driver |
/usr/local/Ascend/driver |
NPU驱动文件 |
/usr/local/dcmi |
/usr/local/dcmi |
DCMI接口 |
/usr/local/bin/npu-smi |
/usr/local/bin/npu-smi |
NPU管理工具 |
/etc/ascend_install.info |
/etc/ascend_install.info |
Ascend安装信息 |
/usr/local/sbin |
/usr/local/sbin |
系统管理工具 |
/etc/hccn.conf |
/etc/hccn.conf |
HCCL网络配置 |
/usr/bin/hccn_tool |
/usr/bin/hccn_tool |
HCCL工具 |
- 数据和模型目录
宿主机路径 | 容器内路径 | 用途 |
---|---|---|
/data |
/data |
数据根目录 |
$MODEL_PATH |
$MODEL_PATH |
模型文件目录 |
$LOG_PATH |
$LOG_PATH |
日志文件目录 |
$SCRIPTS_PATH |
$SCRIPTS_PATH |
脚本文件目录 |
$CODE_PATH |
$CODE_PATH |
代码库目录 |
{{ ranktable_save_path }} |
{{ ranktable_save_path }} |
RankTable文件目录 |
- 系统配置目录
宿主机路径 | 容器内路径 | 用途 |
---|---|---|
/tmp |
/tmp |
临时文件目录 |
/usr/share/zoneinfo/Asia/Shanghai |
/etc/localtime |
时区配置文件 |
端口规划 (基于配置参数):
全局代理:
端口: proxy_port + node_rank
例如: 8080, 8081, 8082...
Prefill服务:
Master端口: global_port_base + port_offset.P + node_rank
API端口: base_api_port + port_offset.P + node_rank
例如: 8503, 9001 (P0), 8504, 9002 (P1)
Decode服务:
Master端口: global_port_base + port_offset.D
API端口: base_api_port + port_offset.D + node_rank
例如: 8603, 9101 (D0), 8603, 9102 (D1)
内部通信:
HCCL通信: 动态分配
KV缓存: 5568 (ZMQ)
健康检查: HTTP探针
tools/
├── README.md # PD运行文档,包含详细的部署示例
├── scripts/ # 核心脚本工具
│ ├── pd_run.sh # PD分离服务启动脚本
│ ├── pd_ranktable_tools.py # Ranktable生成和管理工具
│ ├── start_api_servers.py # API服务器启动脚本
│ ├── global_proxy.sh # 全局代理启动脚本
│ ├── test_start_api_servers_qwen.sh # Qwen模型测试脚本
│ ├── result.json # 测试结果文件
│ └── apiserverlog/ # API服务器日志目录
│ └── server_0.log # 服务器日志文件
├── docker/ # Docker容器化工具
│ ├── build_base_py311.sh # Python 3.11基础镜像构建脚本
│ ├── build_vllm.sh # vLLM镜像构建脚本
│ ├── Dockerfile.openEuler.py311.CANNdev.910c # 华为昇腾环境Dockerfile
│ └── Dockerfile.vllm-omni.source # vLLM-omni源码Dockerfile
└── ansible/ # Ansible自动化部署工具
├── README.md # Ansible部署文档
├── omni_infer_inventory_used_for_CI.yml # CI环境清单配置
├── omni_infer_inventory_user_for_long_term_test.yml # 长期测试环境清单
├── omni_infer_server_used_for_CI.yml # CI环境服务器配置
├── omni_infer_server_used_for_long_term_test.yml # 长期测试服务器配置
└── template/ # 配置模板目录
├── README.md # 模板使用说明
├── omni_infer_inventory_used_for_2P1D.yml # 2P1D部署模板
├── omni_infer_inventory_used_for_4P1D.yml # 4P1D部署模板
└── omni_infer_server_template.yml # 服务器配置模板
Docker目录相关说明已在部署视图页体现,本节不再赘述
- Inventory脚本中定义了主机相关的信息,指定P、D、C主机组,以及相关的参数介绍,详见omni_infer_inventory_used_for_2P1D.yml
- Server_Template中定义了各主机组上的执行任务,详见omni_infer_server_template
执行过程
- 连接各服务器
-
SSH连接建立:
- 使用
ansible_user
指定的用户 - 通过
ansible_ssh_private_key_file
指定的私钥进行认证 - 使用
ansible_ssh_common_args
中的SSH参数
- 使用
-
主机组管理:
- 根据inventory文件中的
children
定义主机组 - 每个主机组(P、D、C)代表不同的角色
- 根据inventory文件中的
-
SSH连接建立:
- Task执行
-
任务顺序:
- 任务按照在playbook中定义的顺序执行
- 使用
gather_facts: yes
收集目标主机信息
-
错误处理:
-
any_errors_fatal: true
确保任何错误都会停止执行 -
max_fail_percentage: 0
不允许任何失败
-
-
条件执行:
- 使用
when
条件控制任务执行 - 使用
run_once: yes
确保任务只执行一次
- 使用
-
任务顺序:
这个Ansible脚本主要用于部署和管理一个分布式AI推理系统,包括Docker容器的管理、代码同步、服务器启动等操作。通过合理的标签管理和条件控制,可以灵活地执行不同的部署阶段。
graph TD
A[环境准备] --> B[容器管理]
B --> C[Ranktable生成]
C --> D[服务启动]
D --> E[代理配置]
A1[创建目录<br/>设置环境变量] --> A
B1[停止旧容器<br/>启动新容器] --> B
C1[生成prefill ranktable<br/>生成decode ranktable<br/>合并全局ranktable] --> C
D1[启动decode服务<br/>等待80秒<br/>启动prefill服务] --> D
E1[配置nginx代理<br/>启动负载均衡] --> E
执行主机: P组、D组、C组的所有主机
主要任务:
- 生成容器名称(添加主机名后缀)
- 检查并删除已存在的容器
- 启动新的Docker容器
关键命令:
# 启动prefill容器
docker run -it --shm-size=500g [各种挂载参数] -d --name $DOCKER_NAME_P $DOCKER_IMAGE_ID
# 启动decode容器
docker run -it --shm-size=500g [各种挂载参数] -d --name $DOCKER_NAME_D $DOCKER_IMAGE_ID
# 启动proxy容器
docker run -it --shm-size=500g [各种挂载参数] -d --name $DOCKER_NAME_C $DOCKER_IMAGE_ID
执行主机: 所有主机
主要任务:
- 获取执行器IP地址
- 删除目标机器上的旧代码
- 同步代码到所有实例
- 在容器内更新代码
- 下载vllm,对齐软件依赖
关键命令:
# 同步代码
synchronize: src: "{{ ansible_env.CODE_PATH }}/omniinfer" dest: "{{ ansible_env.CODE_PATH }}/"
# 容器内更新代码
docker exec $DOCKER_NAME_P /bin/bash -c ' \
cd /data/local_code_path/omniinfer/infer_engines && \
git config --global --add safe.directory /data/local_code_path/omniinfer/infer_engines/vllm && \
cd vllm && git checkout -f && \
cd .. && \
bash bash_install_code.sh && \
pip uninstall vllm -y && \
pip uninstall omniinfer -y && \
cd vllm && \
SETUPTOOLS_SCM_PRETEND_VERSION=0.9.0 VLLM_TARGET_DEVICE=empty pip install -e . && \
cd ../../ && \
pip install -e . && \
pip uninstall numpy -y && \
pip install numpy==1.26'
执行主机: P组、D组主机
主要任务:
- 生成prefill ranktable文件
- 生成decode ranktable文件
- 生成全局ranktable文件
- 同步ranktable文件到所有实例
关键命令:
# 生成prefill ranktable
python ${CODE_PATH}/omniinfer/tools/scripts/pd_ranktable_tools.py \
--mode gen \
--prefill-server-list "${PREFILL_SERVER_LIST}" \
--api-server \
--save-dir ${PREFILL_RANKTABLE_SAVE_PATH}
# 生成decode ranktable
python ${CODE_PATH}/omniinfer/tools/scripts/pd_ranktable_tools.py \
--mode gen \
--decode-server-list ${DECODE_SERVER_LIST} \
--save-dir ${DECODE_RANKTABLE_SAVE_PATH}
# 生成全局ranktable
python ${CODE_PATH}/omniinfer/tools/scripts/pd_ranktable_tools.py \
--mode merge-all \
--api-server-list ${api_server_files} \
--prefill-server-list ${prefill_local_ranktable_merge} \
--decode-server-list ${decode_local_ranktable_merge} \
--save-dir ${RANKTABLE_SAVE_PATH}/global
执行主机: P组、D组主机
主要任务:
- 杀死现有Python进程
- 启动prefill服务
- 启动decode服务
关键命令:
# 杀死Python进程
ps aux | grep "python" | grep -v "grep" | awk '{print $2}' | xargs kill -9
# 启动prefill服务
bash ${CODE_PATH}/omniinfer/tools/scripts/pd_run.sh \
--global-rank-table-path "${RANKTABLE_SAVE_PATH}/global/global_ranktable_merge.json" \
--rank-table-path ${LOCAL_RANKTABLE_FLIE} \
--local-decode-server-ip-list "$SERVER_IP_LIST" \
--global-decode-server-ip-list "$SERVER_IP_LIST" \
--prefill-pod-num ${PREFILL_POD_NUM} \
--gloo-socket-ifname ${SOCKET_IFNAME} \
--tp-socket-ifname ${SOCKET_IFNAME} \
--model-path ${MODEL_PATH} \
--master-ip ${HOST_IP} \
--role "prefill" \
--kv-role "kv_producer" \
--max-model-len ${MODEL_LEN_MAX_PREFILL} \
--master-port ${MASTER_PORT} \
--base-api-port ${API_PORT} \
--tp ${PREFILL_TENSOR_PARALLEL_SIZE} \
--ascend-rt-visible-devices "${PREFILL_SERVER_LIST}" \
--kv-rank ${KV_RANK} \
--kv-engine-id ${KV_RANK} \
--kv-parallel-size ${KV_PARALLEL_SIZE} \
--model-extra-cfg-path ${MODEL_EXTRA_CFG_PATH} \
--gpu-util ${GPU_UTIL} \
--vllm-enable-mc2 ${VLLM_ENABLE_MC2} \
--extra-args "${EXTRA_ARGS}" \
--hccl-buffsize "${HCCL_BUFFSIZE}" \
--hccl-op-expansion-mode "${HCCL_OP_EXPANSION_MODE}" \
--log-dir "${LOG_PATH}"
# 启动decode服务
bash ${CODE_PATH}/omniinfer/tools/scripts/pd_run.sh \
--global-rank-table-path "${RANKTABLE_SAVE_PATH}/global/global_ranktable_merge.json" \
--rank-table-path ${LOCAL_RANKTABLE_FLIE} \
--local-decode-server-ip-list "$SERVER_IP_LIST" \
--global-decode-server-ip-list "$SERVER_IP_LIST" \
--prefill-pod-num ${PREFILL_POD_NUM} \
--gloo-socket-ifname ${SOCKET_IFNAME} \
--tp-socket-ifname ${SOCKET_IFNAME} \
--num-servers ${NUM_SERVERS} \
--num-dp ${dp} \
--server-offset ${config_dict[$HOST]:-0} \
--model-path ${MODEL_PATH} \
--master-ip ${HOST_IP} \
--role "decode" \
--kv-role "kv_consumer" \
--max-model-len ${MODEL_LEN_MAX_DECODE} \
--master-port ${MASTER_PORT} \
--base-api-port ${API_PORT} \
--tp ${DECODE_TENSOR_PARALLEL_SIZE} \
--kv-rank ${PREFILL_POD_NUM} \
--kv-engine-id ${PREFILL_POD_NUM} \
--kv-parallel-size ${KV_PARALLEL_SIZE} \
--model-extra-cfg-path ${MODEL_EXTRA_CFG_PATH} \
--gpu-util ${GPU_UTIL} \
--additional-config "$ADDITIONAL_CONFIG" \
--vllm-enable-mc2 ${VLLM_ENABLE_MC2} \
--extra-args "${EXTRA_ARGS}" \
--hccl-buffsize "${HCCL_BUFFSIZE}" \
--hccl-op-expansion-mode "${HCCL_OP_EXPANSION_MODE}" \
--log-dir "${LOG_PATH}"
执行主机: C组主机
主要任务:
- 杀死现有nginx进程
- 下载并编译nginx
- 启动全局代理服务
关键命令:
# 杀死nginx进程
ps aux | grep "nginx" | grep -v "grep" | awk '{print $2}' | xargs kill -9
# 下载nginx
wget --no-check-certificate "https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"
# 编译nginx
bash build.sh
# 启动代理服务
bash global_proxy.sh \
--listen-port "$PROXY_NODE_PORT" \
--prefill-servers-list "$prefill_result" \
--decode-servers-list "$decode_result" \
--log-file /dev/shm/trace/logs/nginx_error.log \
--log-level notice \
--core-num 4 \
--start-core-index 16
执行主机: 执行器主机
主要任务:
- 创建日志目录
- 从所有机器拉取日志到执行器
关键命令:
# 创建日志目录
mkdir -p "{{ ansible_env.LOG_PATH_IN_EXECUTOR }}/{{ inventory_hostname }}"
# 拉取日志
synchronize: mode: pull src: "{{ ansible_env.LOG_PATH }}" dest: "{{ ansible_env.LOG_PATH_IN_EXECUTOR }}/{{ inventory_hostname }}/"
├── scripts/ # 核心脚本工具
│ ├── pd_run.sh # PD分离服务启动脚本
│ ├── pd_ranktable_tools.py # Ranktable生成和管理工具
│ ├── start_api_servers.py # API服务器启动脚本
│ ├── global_proxy.sh # 全局代理启动脚本
│ ├── test_start_api_servers_qwen.sh # Qwen模型测试脚本
│ ├── result.json # 测试结果文件
│ └── apiserverlog/ # API服务器日志目录
│ └── server_0.log # 服务器日志文件
执行脚本:
# 生成prefill ranktable
python ${CODE_PATH}/omniinfer/tools/scripts/pd_ranktable_tools.py \
--mode gen \
--prefill-server-list "${PREFILL_SERVER_LIST}" \
--api-server \
--save-dir ${PREFILL_RANKTABLE_SAVE_PATH}
# 生成decode ranktable
python ${CODE_PATH}/omniinfer/tools/scripts/pd_ranktable_tools.py \
--mode gen \
--decode-server-list ${DECODE_SERVER_LIST} \
--save-dir ${DECODE_RANKTABLE_SAVE_PATH}
# 生成全局ranktable
python ${CODE_PATH}/omniinfer/tools/scripts/pd_ranktable_tools.py \
--mode merge-all \
--api-server-list ${api_server_files} \
--prefill-server-list ${prefill_local_ranktable_merge} \
--decode-server-list ${decode_local_ranktable_merge} \
--save-dir ${RANKTABLE_SAVE_PATH}/global
执行结果:Merge后的全局rankTable:
{
"version": "1.0",
"status": "completed",
"server_group_list": [
{
"group_id": "0",
"server_count": "1",
"server_list": [
{
"server_id": "host_ip",
"server_ip": "host_ip"
}
]
},
{
"group_id": "1",
"server_count": "1",
"server_list": [
{
"server_id": "host_ip",
"server_ip": "host_ip",
"device": [
{
"device_id": "0",
"device_ip": "device_ip_0",
"rank_id": "0"
},
{
"device_id": "1",
"device_ip": "device_ip_1",
"rank_id": "1"
}
// ... 更多设备
]
}
// ... 更多Server
]
},
{
"group_id": "2",
"server_count": "1",
"server_list": [
{
"server_id": "host_ip",
"server_ip": "host_ip",
"device": [
{
"device_id": "0",
"device_ip": "device_ip_0",
"rank_id": "0"
},
{
"device_id": "1",
"device_ip": "device_ip_1",
"rank_id": "1"
}
// ... 更多设备
]
}
// ... 更多Server
]
}
]
}
RankTable的作用:
- 用于初始化HCCL集合通信库
# 在pd_run.sh中使用ranktable配置分布式通信
--global-rank-table-path "${RANKTABLE_SAVE_PATH}/global/global_ranktable_merge.json" \
--rank-table-path ${LOCAL_RANKTABLE_FLIE}
- rankTable中的服务器信息通过命令行的方式传递给Global_Proxy(Ngnix),做上层负载均衡使用
# 在部署脚本中,ranktable信息被转换为服务器列表
prefill_result="{{ PREFILL_API_SERVER_LIST }}"
decode_result="{{ DECODE_API_SERVER_LIST }}"
# 然后传递给Global_Proxy
bash global_proxy.sh \
--prefill-servers-list "$prefill_result" \
--decode-servers-list "$decode_result"
调用过程:pd_run.sh ==> start_api_server.py ==> 设置环境变量、生成vllm启动脚本并启动子进程 ==> 启动健康检查
vllm执行脚本示例(以环境实测为准):
vllm serve ${MODEL_PATH} \
--trust-remote-code \
--gpu-memory-utilization ${GPU_UTIL} \
--block_size 128 \
--tensor-parallel-size ${PREFILL_TENSOR_PARALLEL_SIZE} \
--data-parallel-size 1 \
--data-parallel-size-local 1 \
--data-parallel-address ${HOST_IP} \
--data-parallel-rpc-port ${MASTER_PORT} \
--port ${API_PORT} \
--served-model-name "deepseek" \
--max-model-len ${MODEL_LEN_MAX_PREFILL} \
--enable-mtp \
--speculative_config '{"method": "mtp", "num_speculative_tokens": 1}' \
--kv-transfer-config '${KV_TRANSFER_CONFIG}' \
--additional-config '${ADDITIONAL_CONFIG}' \
${EXTRA_ARGS}