Table of Contents

国产化DCU 大模型推理服务容器化部署实践

2 21.3~27.4 min

DCU 大模型推理服务容器化部署实践

1. 背景与目标

甲方局里到了一批国产化服务器, 国产化显卡部署 LLM 有亿点点坐牢(

本项目基于国产 DCU 加速卡和 Docker Compose,构建了一套可拆分、可独立启停、可通过统一网关访问的大模型推理服务部署方案。核心目标包括:

  • 通过容器化屏蔽驱动、运行时、Python 依赖和模型服务之间的差异。

  • 使用 vLLM 承载文本、多模态和语音模型推理。

  • 使用 LiteLLM 作为统一 OpenAI 兼容 API 网关,降低业务系统接入成本。

  • 将 Embedding、Reranker、文档解析、向量数据库等能力纳入同一部署体系。

  • 在 PCIe 互联 DCU 环境下,通过模型量化、张量并行、NUMA 亲和性和通信参数调优提升稳定性与资源利用率。

2. 服务器环境

本次部署基于一台海光 DCU 服务器,整体资源特点是 CPU 核心数和系统内存充足,GPU 总显存达到 256GB,适合承载多个中大型推理服务和检索增强组件。

2.1 硬件配置

组件

详细参数

备注

CPU

Hygon 海光 x86_64

192 核心,适合高并发请求调度和数据预处理

内存 RAM

565.1 GiB

适合模型加载、缓存和大批量文档处理

AI 加速卡 DCU

4x Hygon DCU K100_AI

单卡 64GB,总显存 256GB

系统盘

约 400GB

用于操作系统和基础软件

高速盘 NVMe

1.8TB SSD,设备 /dev/sdb,挂载点 /data/fast

用于 Docker 数据和模型权重热加载

数据盘 HDD

22TB HDD,设备 /dev/sdc,挂载点 /data/storage

用于原始数据集、冷备份和日志归档

这类硬件配置的优势是总显存容量较大、CPU 与内存资源充裕,可以同时部署文本模型、语音模型、Embedding / Reranker 和文档解析服务。主要约束在于 GPU 间互联能力和单卡显存带宽,因此模型并行策略需要谨慎设计。

2.2 操作系统与驱动环境

项目

配置

操作系统

UOS Server 20

Kernel

4.19.90 系列,适配国产硬件

架构

x86_64

驱动状态

Kernel Driver Active

异构计算软件栈

DTK-25.04.4

DTK 安装路径

/opt/dtk

环境变量

通过 source /opt/dtk/env.sh 加载

监控工具

rocm-smihy-smi

驱动和运行时版本对 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 适配问题。处理顺序:

  1. 确认模型配置中的 architecture。

  2. 确认镜像内 Transformers 版本。

  3. 确认 vLLM 是否支持该架构。

  4. 必要时构建专用离线镜像,固定依赖版本。

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. 实践总结

这套部署方案的核心经验可以总结为五点:

  1. Compose 拆分服务边界:每个模型独立编排,降低变更和故障影响范围。

  2. LiteLLM 统一接入协议:业务方只面向统一 OpenAI 兼容入口,后端模型可以持续演进。

  3. DCU 镜像要保持运行时一致性:不要混用不匹配的 DTK、PyTorch、vLLM 和 Transformers 版本。

  4. PCIe 环境要谨慎使用多卡并行:TP 解决显存容量问题,但会引入通信开销。

  5. 性能调优先稳定后吞吐:先让模型可重复启动、健康检查稳定,再逐步调上下文、batch 和并发参数。

从工程角度看,大模型推理平台不是单个模型服务,而是一组模型、网关、检索、解析、存储和运维策略的组合。容器化的价值在于把这些差异封装起来,让服务能被独立替换、独立调优和独立排错。

12. 后续优化方向

后续可以从以下方向继续演进:

  • 引入统一配置模板,减少不同 Compose 文件之间的重复配置。

  • 将密钥、端口和路径全部迁移到 .env 或 Secret 管理系统。

  • 增加标准化压测脚本,记录不同模型在不同 batch 和上下文长度下的性能曲线。

  • 增加网关层限流、熔断和模型降级策略。

  • 引入服务监控,采集 GPU 利用率、显存、请求延迟、错误率和吞吐量。

  • 对 RAG 链路补充端到端示例,包括文档解析、向量化、入库、检索、重排序和生成。