国产化DCU 大模型推理服务容器化部署实践
DCU 大模型推理服务容器化部署实践
1. 背景与目标
甲方局里到了一批国产化服务器, 国产化显卡部署 LLM 有亿点点坐牢(
本项目基于国产 DCU 加速卡和 Docker Compose,构建了一套可拆分、可独立启停、可通过统一网关访问的大模型推理服务部署方案。核心目标包括:
通过容器化屏蔽驱动、运行时、Python 依赖和模型服务之间的差异。
使用 vLLM 承载文本、多模态和语音模型推理。
使用 LiteLLM 作为统一 OpenAI 兼容 API 网关,降低业务系统接入成本。
将 Embedding、Reranker、文档解析、向量数据库等能力纳入同一部署体系。
在 PCIe 互联 DCU 环境下,通过模型量化、张量并行、NUMA 亲和性和通信参数调优提升稳定性与资源利用率。
2. 服务器环境
本次部署基于一台海光 DCU 服务器,整体资源特点是 CPU 核心数和系统内存充足,GPU 总显存达到 256GB,适合承载多个中大型推理服务和检索增强组件。
2.1 硬件配置
这类硬件配置的优势是总显存容量较大、CPU 与内存资源充裕,可以同时部署文本模型、语音模型、Embedding / Reranker 和文档解析服务。主要约束在于 GPU 间互联能力和单卡显存带宽,因此模型并行策略需要谨慎设计。
2.2 操作系统与驱动环境
驱动和运行时版本对 DCU 推理服务影响很大。通用模型镜像通常依赖宿主机 DTK 与 hyhal,专用模型镜像则可能内置特定版本运行时。部署时需要明确镜像运行时来源,避免宿主机库覆盖容器内依赖。
3. 总体架构
整体架构采用“统一入口 + 多后端模型服务 + 检索增强组件”的分层设计。
业务系统 / 应用平台
|
v
LiteLLM Proxy
统一 OpenAI 兼容 API 网关
|
+------------------+------------------+------------------+
| | | |
v v v v
文本 LLM 服务 视觉多模态服务 语音识别服务 Embedding / Reranker
vLLM vLLM vLLM TEI 或 vLLM
|
v
文档解析 / 向量数据库 / 对象存储
MinerU / Milvus / MinIO
这一架构有几个关键特点:
网关层统一协议:对外尽量暴露 OpenAI 兼容接口,业务方不需要感知后端模型部署细节。
模型层独立编排:每个模型对应独立 Compose 文件,可以单独启动、停止、迁移或替换。
资源层显式分配:通过环境变量和 Compose 配置绑定 DCU 设备,避免多个重型服务争抢同一卡。
能力层可组合:文本生成、视觉理解、语音识别、文档解析和向量检索可以按业务链路组合成 RAG、知识库、文档问答等应用。
4. 项目结构设计
项目根目录以 Compose 文件和说明文档为主,各能力按模块拆分。
docker-compose/
├── docker-compse.yml # LiteLLM Proxy 网关
├── litellm_config.yaml # LiteLLM 模型路由配置
├── embedding-reranker.yml # Embedding / Reranker CPU 版本
├── embedding-reranker-gpu.yml # Embedding / Reranker GPU 版本
├── qwen/ # 文本与视觉模型服务
├── qwen3-asr/ # 语音识别服务
├── mineru/ # 文档解析服务
├── milvus/ # 向量数据库服务
├── cosyVoice3/ # 语音合成服务
├── scripts/ # 镜像构建、保存、加载脚本
└── README.md # 项目说明
这种组织方式避免将所有服务塞进一个 Compose 文件。对于大模型平台来说,模型服务的镜像、依赖、设备挂载、启动参数、健康检查时间和显存占用都不同,拆分后更容易做灰度调整和故障定位。
5. 核心组件说明
5.1 LiteLLM 统一网关
LiteLLM Proxy 位于所有模型服务前面,负责把业务请求路由到后端模型服务。它的主要价值不是提升单模型性能,而是统一接入方式:
对外提供 OpenAI 兼容 API。
将模型名称映射到不同后端服务。
对业务方屏蔽后端端口、运行框架和模型版本差异。
便于后续接入鉴权、日志、限流和计费等平台能力。
分享时需要强调一点:网关配置中不应硬编码真实密钥或数据库连接信息。生产环境建议使用环境变量、密钥管理系统或部署平台的 Secret 机制注入。
配置示例:
general_settings:
master_key:"${LITELLM_MASTER_KEY}"
model_list:
-model_name: qwen-chat
litellm_params:
model: openai/qwen-chat
api_base: <http://127.0.0.1>:<MODEL_PORT>/v1
api_key:"${BACKEND_API_KEY}"
5.2 vLLM 模型服务
文本、多模态和语音识别服务主要由 vLLM 承载。不同模型使用独立 Compose 文件,差异体现在:
使用的基础镜像不同。
需要挂载的 DCU 设备不同。
是否需要挂载宿主机 DTK 或 hyhal。
模型路径、模型名称、上下文长度和并发参数不同。
是否启用工具调用、多模态输入限制、prefix caching、chunked prefill 等能力。
典型 vLLM 服务会包含以下配置要点:
services:
model-service:
image: <PRIVATE_REGISTRY>/<VLLM_IMAGE>:<TAG>
network_mode:"host"
ipc:"host"
devices:
- /dev/kfd:/dev/kfd
- /dev/dri:/dev/dri
environment:
- HIP_VISIBLE_DEVICES=<GPU_IDS>
- HF_HOME=<HF_CACHE_DIR>
volumes:
- <MODEL_DIR>:/app/models
- <LOG_DIR>:/var/log/vllm
command:>
vllm serve /app/models/<MODEL_NAME>
--host 0.0.0.0
--port <MODEL_PORT>
--served-model-name <SERVED_MODEL_NAME>
--tensor-parallel-size <TP_SIZE>
--dtype float16
--disable-log-requests
这里的关键不是参数越多越好,而是根据硬件互联、模型架构和显存余量做取舍。
5.3 Embedding 与 Reranker
Embedding 和 Reranker 是知识库和 RAG 链路的基础能力。它们与大语言模型的资源特征不同:
模型体积较小。
请求通常更高频。
对吞吐和批处理更敏感。
可以根据资源情况在 CPU 版和 GPU 版之间切换。
本项目保留 CPU 和 GPU 两套 Compose 文件,是一个实用设计。GPU 资源紧张时,Embedding / Reranker 可以先运行在 CPU 上;当检索链路吞吐成为瓶颈时,再切换到 GPU 版本。
5.4 文档解析与向量数据库
除了模型推理服务,项目还包含文档解析和向量数据库组件:
MinerU:负责 PDF、图片等非结构化文档解析。
Milvus:负责向量数据存储与检索。
MinIO:作为对象存储后端。
Attu:作为 Milvus 管理界面。
这些组件使平台具备从“文档输入”到“向量化检索”再到“LLM 生成回答”的完整 RAG 基础链路。
6. DCU 环境下的关键适配经验
6.1 设备挂载
DCU 容器通常需要挂载加速设备,例如:
devices:
- /dev/kfd:/dev/kfd
- /dev/dri:/dev/dri
部分镜像或运行时还需要额外设备、安全配置或共享内存配置。对于大模型服务,ipc: "host" 和较大的 shm_size 往往能减少启动和运行时问题。
6.2 DTK 与镜像版本匹配
DCU 推理服务对 DTK、运行时库、PyTorch、vLLM、Transformers 和模型架构适配关系较敏感。实践中需要区分两类镜像:
依赖宿主机 DTK 的通用镜像:需要挂载宿主机 DTK 和 hyhal。
自带完整运行时的专用镜像:不应再挂载宿主机运行时,避免容器内库被覆盖。
这是 DCU 部署中非常常见的故障来源。分享时可以把它总结为一句经验:镜像如果自带运行时,就让镜像自洽;镜像如果依赖宿主机运行时,就保证宿主机版本与镜像预期一致。
6.3 PCIe 互联下的张量并行取舍
在 PCIe 互联环境中,Tensor Parallelism 并不是越大越好。TP 增大后,每张卡承担的模型权重减少,但卡间 AllReduce 通信会增加。如果没有高速互联,通信开销可能抵消并行收益。
实践中的取舍思路:
大模型无法单卡容纳时,使用 TP 拆分模型。
如果模型量化后可用较小 TP 运行,优先降低 TP,减少通信。
对 PCIe 环境,通常需要禁用不适配的自定义 AllReduce。
多卡部署前先明确模型是显存容量受限、显存带宽受限,还是卡间通信受限。
6.4 NUMA 亲和性
当 GPU 挂载在特定 NUMA 区域时,容器可以通过 cpuset 绑定更接近的 CPU 核,减少跨 NUMA 访问带来的延迟。它不能解决所有性能问题,但对模型加载、tokenization、请求调度和 CPU 侧预处理有帮助。
示例:
services:
model-service:
cpuset:"<CPU_CORE_RANGE_CLOSE_TO_GPU>"
6.5 显存预算
显存预算需要同时考虑:
模型权重。
KV Cache。
CUDA/HIP 图或 eager 执行开销。
batch、sequence、prefill 参数。
多模态输入带来的额外缓存。
常见参数包括:
--gpu-memory-utilization
--max-model-len
--max-num-batched-tokens
--max-num-seqs
--enable-prefix-caching
--enable-chunked-prefill
调参时建议先保证服务稳定启动,再逐步提高上下文长度、批处理 token 数和并发序列数。
7. 模型服务参数设计
7.1 文本模型
文本模型通常承担对话、代码生成、工具调用和 Agent 场景。参数设计重点是:
根据显存容量选择 FP16、AWQ、compressed-tensors 等精度或量化方式。
根据互联能力选择合适 TP。
根据业务上下文长度设置
max-model-len。对工具调用模型配置 tool parser 和 chat template。
对生产日志做降噪,避免记录完整请求内容。
7.2 视觉多模态模型
视觉模型需要额外关注多模态输入限制。比如单次请求允许几张图片、是否允许视频、上下文长度如何与图像 token 共同占用预算。
建议显式设置多模态输入上限:
--limit-mm-per-prompt '{"image":1,"video":0}'
这样可以避免单个请求占用过多显存,影响其他服务稳定性。
7.3 语音识别模型
语音识别模型一般不需要多卡 TP,但需要关注音频输入长度、并发请求数和模型特定算子兼容性。对单卡部署而言,更重要的是避免和其他重型服务共用同一卡。
7.4 文档解析模型
文档解析服务的负载特征与纯 LLM 不同,通常更依赖文件上传、解析队列、OCR/VLM 处理和结果写回。部署时需要关注:
上传文件大小限制。
临时文件目录与持久化目录。
是否与 OpenAI 兼容接口共用端口。
GPU 分配是否与其他模型冲突。
8. 服务编排与运维策略
8.1 单服务独立启停
项目将不同能力拆成独立 Compose 文件。这样做的收益是:
某个模型重启不影响全部平台。
便于按 GPU 资源决定启动哪些服务。
参数变更和镜像替换的风险边界更小。
排查问题时可以聚焦单个容器。
通用启动方式可以表达为:
docker compose -f <SERVICE_COMPOSE_FILE> up -d
8.2 健康检查
每个服务应提供健康检查。对于大模型服务,启动时间可能较长,因此健康检查的 start_period 需要比普通 Web 服务更宽松。
healthcheck:
test:["CMD","curl","-f","<http://localhost>:<PORT>/health"]
interval: 30s
timeout: 10s
retries:5
start_period: 300s
8.3 日志策略
生产环境建议区分三类日志:
容器运行日志:用于判断服务是否启动、是否 OOM、是否模型加载失败。
vLLM 编译和缓存日志:用于排查首次启动慢、算子编译失败等问题。
网关访问日志:用于统计调用量、错误率和延迟。
同时建议关闭模型服务的完整请求日志,避免业务数据或用户输入进入容器日志。
9. 常见问题与排查思路
9.1 服务无法启动
优先检查:
模型目录是否存在。
镜像内依赖是否匹配模型架构。
DTK、hyhal 和容器内运行时是否冲突。
DCU 设备是否正确挂载。
shm_size是否过小。容器是否有足够权限访问设备。
9.2 模型架构不识别
这通常不是 Compose 问题,而是 Transformers、vLLM 或模型 remote code 适配问题。处理顺序:
确认模型配置中的 architecture。
确认镜像内 Transformers 版本。
确认 vLLM 是否支持该架构。
必要时构建专用离线镜像,固定依赖版本。
9.3 量化参数冲突
模型名称中出现 AWQ 不代表启动时一定要手动指定 --quantization awq。部分模型实际使用 compressed-tensors 或其他量化配置,vLLM 可以从模型配置中自动识别。遇到量化冲突时,应优先查看模型配置文件,而不是仅凭模型名称判断。
9.4 多卡通信性能差
PCIe 环境下,多卡通信经常成为瓶颈。排查时关注:
TP 是否过大。
是否启用了不适配当前硬件的 AllReduce 实现。
GPU 是否跨 NUMA 或跨 PCIe switch。
请求是否因为 batch 设置过大导致同步等待变长。
9.5 并发上不去
并发能力通常受以下因素共同影响:
剩余显存决定 KV Cache 上限。
显存带宽影响 token 解码速度。
上下文长度影响单请求显存占用。
batch 参数影响吞吐和首 token 延迟。
网关和后端超时设置影响长请求稳定性。
调优时建议用压测数据驱动,不要只看单次 curl 是否成功。
10. 配置与安全实践
模型平台通常会涉及网关鉴权、模型路径、运行端口、日志目录和后端服务地址。为了便于维护,建议将这些内容配置化管理:
网关密钥、后端访问凭证和数据库连接信息通过环境变量或 Secret 机制注入。
模型目录、缓存目录、日志目录和端口号集中配置,避免散落在多个脚本中。
生产日志避免记录完整请求体,尤其是用户输入、文件内容和业务上下文。
健康检查、启动脚本和压测脚本使用统一变量,降低环境迁移成本。
镜像版本、模型版本和关键依赖版本保持可追溯,便于回滚和复现问题。
API 调用示例:
curl http://<SERVER_HOST>:<GATEWAY_PORT>/v1/chat/completions \\
-H "Authorization: Bearer <API_KEY>" \\
-H "Content-Type: application/json" \\
-d '{
"model": "qwen-chat",
"messages": [
{"role": "user", "content": "你好"}
],
"temperature": 0.7
}'
11. 实践总结
这套部署方案的核心经验可以总结为五点:
Compose 拆分服务边界:每个模型独立编排,降低变更和故障影响范围。
LiteLLM 统一接入协议:业务方只面向统一 OpenAI 兼容入口,后端模型可以持续演进。
DCU 镜像要保持运行时一致性:不要混用不匹配的 DTK、PyTorch、vLLM 和 Transformers 版本。
PCIe 环境要谨慎使用多卡并行:TP 解决显存容量问题,但会引入通信开销。
性能调优先稳定后吞吐:先让模型可重复启动、健康检查稳定,再逐步调上下文、batch 和并发参数。
从工程角度看,大模型推理平台不是单个模型服务,而是一组模型、网关、检索、解析、存储和运维策略的组合。容器化的价值在于把这些差异封装起来,让服务能被独立替换、独立调优和独立排错。
12. 后续优化方向
后续可以从以下方向继续演进:
引入统一配置模板,减少不同 Compose 文件之间的重复配置。
将密钥、端口和路径全部迁移到
.env或 Secret 管理系统。增加标准化压测脚本,记录不同模型在不同 batch 和上下文长度下的性能曲线。
增加网关层限流、熔断和模型降级策略。
引入服务监控,采集 GPU 利用率、显存、请求延迟、错误率和吞吐量。
对 RAG 链路补充端到端示例,包括文档解析、向量化、入库、检索、重排序和生成。