简介:本文面向开发者和运维工程师,讲解智驾Transformer模型服务从显存与带宽估算、容器化部署,到灰度发布、回滚和故障排查的完整流程。读者可以先用公式估算资源,再用profiler实测校准,并按验收标准分阶段上线,减少OOM和延迟抖动,也减少因估算失误造成的资源浪费。
部署前先回答四个问题。答案决定后面每一步的参数选择,不能跳过。
| 检查项 | 判断标准 | 需要准备的材料 | 不满足时的处理 |
|---|---|---|---|
| 服务形态 | 是在线逐请求推理,还是离线批处理 | 业务的延迟要求(如P99目标)和吞吐要求 | 在线推理优先看延迟,批处理优先看吞吐,两者的batch策略不同,需分别配置 |
| 运行时依赖 | 推理框架、CUDA版本、驱动版本、加速库是否互相兼容 | 框架和加速库的版本矩阵 | 按厂商兼容表选定一组版本,不要混用未验证的组合 |
| 模型与配置文件布局 | 权重、配置、分词或预处理文件是否有固定目录和版本号 | 模型目录结构、文件sha256校验值 | 统一为 models/<版本号>/ 结构,每个版本附带校验文件 |
| 网络与数据依赖 | 上游输入来源、下游调用方、是否需要访问外部存储 | 网络拓扑图、端口列表、鉴权方式 | 为每个依赖列出超时时间和失败后的降级方案 |
在线推理的服务通常还要确认三件事。第一,单次请求的输入形状是否可变,可变时需要设定最大序列长度。第二,是否允许排队,允许排队时需要设定最大队列长度,超出即拒绝。第三,是否有多模型串联,串联时每个模型的显存需要分别估算后再相加。
显存总量 ≈ 权重显存 + KV缓存 + 激活与工作区 + 框架开销 + 预留余量
各项的计算口径如下。
适用边界:公式只给出静态估算。实际峰值会随算子实现、并行策略和动态形状变化,所以公式的结果必须经过第三节的实测校验。
自回归解码阶段,每生成一步,都要从显存读取全部权重和当前的KV缓存。这一阶段通常受访存限制,因此带宽是吞吐的主要约束。
单步访存量 ≈ 权重字节 + KV缓存字节
单步耗时 ≈ 单步访存量 ÷ 有效带宽
吞吐上限(token/s)≈ batch ÷ 单步耗时
有效带宽 = 峰值带宽 × 实测效率系数。峰值带宽从显卡规格书获取,效率系数用带宽测试工具或profiler中的DRAM吞吐数据得到。效率系数一般明显低于1,直接用峰值带宽计算会高估吞吐。
这组公式只适用于解码阶段。输入预填充阶段的计算量更接近算力瓶颈,需要单独估算。卷积层和其他结构的访存模式也不同,不能直接套用。
以下数值为演示用假设,不代表任何硬件或模型的实测结果。
假设条件:参数量10亿,BF16精度,层数24,KV头数8,头维度64,序列长度2048,batch为4。
这个算例说明,在该假设下,权重读取和KV读取各占一部分流量。若序列长度翻倍,KV部分随之翻倍,吞吐上限会明显下降。调参时应先确认哪一项占主导。
估算结果必须用实测验证。推荐按以下步骤执行。
import torchtorch.cuda.reset_peak_memory_stats()# 执行一次完整推理,包括预处理和后处理output = model(inputs)peak_gib = torch.cuda.max_memory_allocated() / 1024 ** 3print(f"peak allocated: {peak_gib:.2f} GiB")
验证标准如下。
如果偏差持续存在,把偏差较大的项单独拆出来测量,然后更新估算模型。这样就形成了“估算、实测、调参”的闭环。
宿主机需要完成以下准备。
docker run --rm --gpus all <基础镜像> nvidia-smi 确认显卡可见。/data/models。模型文件较大,要预留至少为所有保留版本总和1.5倍的空间,给下载和校验留出余量。建议把模型权重放在宿主机,用只读卷挂载进容器,不要打进镜像。这样回滚时只需切换模型路径,不必重新构建镜像。
示例Dockerfile:
# 基础镜像选择与推理框架、CUDA版本匹配的官方镜像,并固定版本标签FROM <推理框架官方基础镜像:固定版本标签>WORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txtCOPY serve/ ./serve/COPY config/ ./config/# 非root用户运行,降低容器内被提权后的影响范围RUN useradd -u 10001 -m appuserUSER 10001ENV MODEL_PATH=/models/currentEXPOSE 8080CMD ["python", "-m", "serve.main", "--config", "config/service.yaml"]
镜像构建完成后,用镜像扫描工具检查高危漏洞。发现问题时先修复基础镜像,不要直接忽略。
启动容器的示例命令如下。路径、版本号和资源限制需要替换为实际值。
docker run -d \--name trans-svc \--gpus all \-p 8080:8080 \-v /data/models:/models:ro \-e MODEL_PATH=/models/v1.2.0 \--memory 16g \--restart unless-stopped \<镜像名:版本标签>
启动参数的含义如下。
-v ... :ro:模型目录只读挂载,服务进程无法修改权重。MODEL_PATH:指向具体版本目录,版本切换和回滚都通过修改这一项完成。--memory:限制容器内存,防止主机内存被耗尽。--restart unless-stopped:容器异常退出后自动重启。这会掩盖故障,因此上线期间要同时监控重启次数。服务配置文件 config/service.yaml 中,建议显式写出以下字段。
| 字段 | 含义 | 设置原则 |
|---|---|---|
max_seq_len |
允许的最大序列长度 | 按第二节的KV公式反推,保证峰值显存不超标 |
max_batch_size |
最大批次 | 与吞吐测试结果一致,超出时排队或拒绝 |
max_queue_len |
最大排队长度 | 设定上限,避免延迟无限增长 |
request_timeout_ms |
单次请求超时 | 略高于P99延迟目标,超时返回明确错误码 |
dtype |
推理精度 | 与估算和实测使用的精度一致 |
安全方面,上线前逐项确认以下内容。
上线前按顺序完成以下检查。