环境准备与首次启动:在 4×A800 上部署 181.3 GiB 权重
文章目录
- [环境准备与首次启动:在 4×A800 上部署 181.3 GiB 权重](#环境准备与首次启动:在 4×A800 上部署 181.3 GiB 权重)
-
- 概览
- [1. 硬件要求:四卡](#1. 硬件要求:四卡)
- [2. 权重清单核对:模型权重的构成](#2. 权重清单核对:模型权重的构成)
- [3. 权重接线:软链接、inode 与空挂载事故](#3. 权重接线:软链接、inode 与空挂载事故)
-
- [3.1 双启动路径一致性约束:由哪一层负责暴露路径差异](#3.1 双启动路径一致性约束:由哪一层负责暴露路径差异)
- [4. 页缓存预热:157 秒的收益](#4. 页缓存预热:157 秒的收益)
-
- [4.1 并发度选择](#4.1 并发度选择)
- [5. 首次启动:376 秒的分阶段记录](#5. 首次启动:376 秒的分阶段记录)
-
- [5.1 就绪:日志三类常见信息](#5.1 就绪:日志三类常见信息)
概览
- 平台配置固定 :4×A800-80GB(SM80 / Ampere,compute capability 8.0),驱动版本已验证为 580.178.04,镜像为
lazymio/vllm-backport:latest-sm80。 - 权重有完整清单 :181.3 GiB / 120 个 safetensors 分片。按
models/README.md从index.json实测的分解:MoE 专家(layers.3..44,共 42 层)163.3 GiB,采用 int4 packed(weight_packed为 I32)加 bf16weight_scale、group_size=32;注意力 11.5、shared experts 2.0、embed+lm_head 2.4、dense MLP 1.5、vision tower 1.05、MTP 头 4.1(均为 bf16)。 --check是只读检查 :覆盖 Docker、驱动、卡号存在性、SM80 验收、内存 ≥200 GiB、/dev/shm≥32 GiB、镜像与 digest 对账、端口占用、权重完整性与四件套、软链接解析并写回.env、磁盘余量、鉴权告警。任何失败项都附原因与修复方式,并生成logs/env-fingerprint.txt,供后续性能对比使用。- 预热是一项可直接计算的工作 :冷 NFS 读速 0.565 GB/s,
warm_cache.sh用多路dd(默认 12 路并发,可用WARM_PARALLEL提高)把 181.3 GiB 读入页缓存,实测耗时 157 s;TP=4时每个 rank 都要完整重读 checkpoint,约 728 GiB,对应 728 ÷ 0.565 ≈ 21.5 分钟,而热读为分钟级。页缓存是内核全局资源,bind mount 共享同一 inode,宿主的预热结果对容器同样有效。 - 启动耗时要按阶段拆分:就绪总时长约 376 s,其中权重加载 228--293 s(纯 I/O 热路径仅约 60--92 s,主要耗时在反序列化),init engine 31--36 s(冷启动为 182 s)。
1. 硬件要求:四卡
| 项目 | 底线 | 技术原因 |
|---|---|---|
| GPU | 4×A800-80GB(SM80,compute_cap 8.0) | 镜像是把新一代引擎能力回移到 SM80 的专项构建;W4A16 走 MARLIN 内核路径(sm80 上有专门实现)。Hopper/Blackwell 不在支持范围内,参数需整套重调 |
| 卡间互联 | 0↔1、2↔3 为 NVLink,跨对走 PCIe 交换机(topo 表显示 PIX) | 这是默认并行配置的前提:TP=2×PP=2 的收益完全建立在「TP 组位于 NVLink 对内」之上。 |
| 驱动 | 580.178.04 + NVIDIA Container Toolkit | 唯一被验证过的版本;Toolkit 是 --gpus 能力的前置条件。驱动换代后任何数字漂移都无法归因,这是把指纹文件列为复现要件的根本原因 |
| Docker | 支持 --gpus 与 compose 的 GPU 预留(已验证 29.8.1) |
compose 路径靠 deploy.resources.reservations.devices 分配卡;count:all 只表示允许使用全部卡,实际卡位由 NVIDIA_VISIBLE_DEVICES 限定------多用户机器上不要删除这一行 |
| 镜像 | lazymio/vllm-backport:latest-sm80,约 30 GB |
必须包含 glm5next 的 PP 实现 make_empty_intermediate_tensors------官方 vllm-openai:glm53-flash-sm80 没有它,PP 启动会直接报 Pipeline parallelism is not supported |
| 主机内存 | ≥200 GiB | 页缓存需要容纳 181.3 GiB 权重;1 TiB 机器上权重可全量常驻,重启耗时从 21 分钟档降到 6 分钟档 |
| 共享内存 | 容器 --shm-size 32gb + --ipc host |
张量并行的多进程共享缓冲与分布式通信共用同一块共享内存 |
| 磁盘 | 仓库旁数 GiB | JIT 缓存实测约 1 GiB,不需要预留大容量 |
- 四张 80 GB 卡合计 320 GiB 显存,容纳 181.3 GiB 权重看似宽裕,但部署的难点集中在动态显存:KV 池、CUDA graph 捕获池、投机解码草稿缓冲以及每层前向的激活峰值需要同时共存。
#mermaid-svg-w0FZnAkqB0kL3o6h{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-w0FZnAkqB0kL3o6h .error-icon{fill:#552222;}#mermaid-svg-w0FZnAkqB0kL3o6h .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-w0FZnAkqB0kL3o6h .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-w0FZnAkqB0kL3o6h .marker{fill:#333333;stroke:#333333;}#mermaid-svg-w0FZnAkqB0kL3o6h .marker.cross{stroke:#333333;}#mermaid-svg-w0FZnAkqB0kL3o6h svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-w0FZnAkqB0kL3o6h p{margin:0;}#mermaid-svg-w0FZnAkqB0kL3o6h .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h .cluster-label text{fill:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h .cluster-label span{color:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h .cluster-label span p{background-color:transparent;}#mermaid-svg-w0FZnAkqB0kL3o6h .label text,#mermaid-svg-w0FZnAkqB0kL3o6h span{fill:#333;color:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h .node rect,#mermaid-svg-w0FZnAkqB0kL3o6h .node circle,#mermaid-svg-w0FZnAkqB0kL3o6h .node ellipse,#mermaid-svg-w0FZnAkqB0kL3o6h .node polygon,#mermaid-svg-w0FZnAkqB0kL3o6h .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-w0FZnAkqB0kL3o6h .rough-node .label text,#mermaid-svg-w0FZnAkqB0kL3o6h .node .label text,#mermaid-svg-w0FZnAkqB0kL3o6h .image-shape .label,#mermaid-svg-w0FZnAkqB0kL3o6h .icon-shape .label{text-anchor:middle;}#mermaid-svg-w0FZnAkqB0kL3o6h .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-w0FZnAkqB0kL3o6h .rough-node .label,#mermaid-svg-w0FZnAkqB0kL3o6h .node .label,#mermaid-svg-w0FZnAkqB0kL3o6h .image-shape .label,#mermaid-svg-w0FZnAkqB0kL3o6h .icon-shape .label{text-align:center;}#mermaid-svg-w0FZnAkqB0kL3o6h .node.clickable{cursor:pointer;}#mermaid-svg-w0FZnAkqB0kL3o6h .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-w0FZnAkqB0kL3o6h .arrowheadPath{fill:#333333;}#mermaid-svg-w0FZnAkqB0kL3o6h .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-w0FZnAkqB0kL3o6h .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-w0FZnAkqB0kL3o6h .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-w0FZnAkqB0kL3o6h .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-w0FZnAkqB0kL3o6h .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-w0FZnAkqB0kL3o6h .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-w0FZnAkqB0kL3o6h .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-w0FZnAkqB0kL3o6h .cluster text{fill:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h .cluster span{color:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-w0FZnAkqB0kL3o6h .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-w0FZnAkqB0kL3o6h rect.text{fill:none;stroke-width:0;}#mermaid-svg-w0FZnAkqB0kL3o6h .icon-shape,#mermaid-svg-w0FZnAkqB0kL3o6h .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-w0FZnAkqB0kL3o6h .icon-shape p,#mermaid-svg-w0FZnAkqB0kL3o6h .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-w0FZnAkqB0kL3o6h .icon-shape .label rect,#mermaid-svg-w0FZnAkqB0kL3o6h .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-w0FZnAkqB0kL3o6h .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-w0FZnAkqB0kL3o6h .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-w0FZnAkqB0kL3o6h :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 由 nvidia-smi topo -m 确定的互联结构
GPU0 ═══ GPU1(NVLink,NV8)
GPU2 ═══ GPU3(NVLink,NV8)
GPU 对之间:PCIe 交换机(PIX),all-reduce 的低带宽路径
默认部署形态的设计依据:
让 TP 的 all-reduce 只发生在 NVLink 对内,
跨对只承担 PP 的一段接力
2. 权重清单核对:模型权重的构成
- 部署权重之前必须核对清单,否则后续任何异常都无法归因。
models/README.md给出了从model.safetensors.index.json逐条实测的分解表:
| 部分 | 体积 | 存储形态 |
|---|---|---|
| MoE 专家(layers.3...44,共 42 层) | 163.3 GiB | int4 packed(weight_packed 为 I32)+ bf16 weight_scale,group_size=32,对称,仅权重(W4A16) |
| MLA / KDA 注意力 | 11.5 GiB | bf16,未量化(ignore 列表命中 self_attn) |
| shared experts | 2.0 GiB | bf16 |
| embed_tokens + lm_head | 2.4 GiB | bf16 |
| dense MLP(layers 0--2) | 1.5 GiB | bf16 |
| vision tower | 1.05 GiB | bf16 |
| MTP 头(layer 45) | 4.1 GiB | bf16,投机解码专用 |
| 合计 | 181.3 GiB | 46 层 = 45 主层 + 1 MTP 层;120 个分片 |
三个值得注意的细节:
- 量化范围是有意选定的 :只对 MoE 专家矩阵使用 int4(其体积占九成,压缩收益最大),注意力等精度敏感部件保留 bf16。所谓 W4A16,精确指的就是文档口径中的 288 个专家矩阵(
gate_proj/up_proj/down_proj)。 - packed 在存储层的表示 :int4 每个元素半字节,safetensors 没有半字节类型,于是以
weight_packed(I32 整型容器)加weight_scale(bf16 反量化缩放系数)成对落盘;group_size=32表示每 32 个权重共用一个缩放系数,推理时按组反量化。 - 三套体积口径可以互相校验:层单价表给出的是 3×0.539 + 42×4.10 + 4.14 ≈ 178 GiB,部件分解表横向加总约 185.9 GiB,分片事实是 181.3 GiB。三套口径互差 2--4%,这在量化权重中属于正常范围(层单价是含尾数的约值,部件表与 index 的分类边界互有交叠)。
一个常见的追问是:int4 配合 group 缩放系数后,每个参数实际占多少字节?可以直接用四则运算得出:pack-quantized 布局下每个权重占 0.5 字节(4 bit);group_size=32 表示每 32 个参数共用一个 bf16 缩放系数,摊到每个参数为 2/32 = 0.0625 字节。
bash
每参数存储 = 0.5 + 0.0625 = 0.5625 字节
对照纯 int4 的 0.5:缩放系数带来 12.5% 存储开销(0.0625 / 0.5)
对照 bf16 的 2 字节:压缩比 2 ÷ 0.5625 ≈ 3.56 倍
- 这12.5%的存储开销正是许多人估算模型体积时系统性偏低的原因。
group_size越小,分组越细、精度越高、存储开销越大,这是一条连续区间,W4A16 选 32 是工程上的折中点。据此可对 163.3 GiB 量化包做数量级估算:163.3 GiB ≈ 1.75×10¹¹ B ÷ 0.5625 ≈ 三千亿参数量级的存储预算。需要注意这是按布局推算的算术结果,而非官方参数表数字;两套口径混用时误差可达两位百分比,只宜作为数量级参考。运行时显存还存在反量化缓冲与缩放系数对齐的中间态,这部分开销在第 02 篇的显存分配与峰值协调中说明。
#mermaid-svg-bAuUUnJ6oSKkJBCh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bAuUUnJ6oSKkJBCh .error-icon{fill:#552222;}#mermaid-svg-bAuUUnJ6oSKkJBCh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bAuUUnJ6oSKkJBCh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .marker.cross{stroke:#333333;}#mermaid-svg-bAuUUnJ6oSKkJBCh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bAuUUnJ6oSKkJBCh p{margin:0;}#mermaid-svg-bAuUUnJ6oSKkJBCh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .cluster-label text{fill:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .cluster-label span{color:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .cluster-label span p{background-color:transparent;}#mermaid-svg-bAuUUnJ6oSKkJBCh .label text,#mermaid-svg-bAuUUnJ6oSKkJBCh span{fill:#333;color:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .node rect,#mermaid-svg-bAuUUnJ6oSKkJBCh .node circle,#mermaid-svg-bAuUUnJ6oSKkJBCh .node ellipse,#mermaid-svg-bAuUUnJ6oSKkJBCh .node polygon,#mermaid-svg-bAuUUnJ6oSKkJBCh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .rough-node .label text,#mermaid-svg-bAuUUnJ6oSKkJBCh .node .label text,#mermaid-svg-bAuUUnJ6oSKkJBCh .image-shape .label,#mermaid-svg-bAuUUnJ6oSKkJBCh .icon-shape .label{text-anchor:middle;}#mermaid-svg-bAuUUnJ6oSKkJBCh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .rough-node .label,#mermaid-svg-bAuUUnJ6oSKkJBCh .node .label,#mermaid-svg-bAuUUnJ6oSKkJBCh .image-shape .label,#mermaid-svg-bAuUUnJ6oSKkJBCh .icon-shape .label{text-align:center;}#mermaid-svg-bAuUUnJ6oSKkJBCh .node.clickable{cursor:pointer;}#mermaid-svg-bAuUUnJ6oSKkJBCh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .arrowheadPath{fill:#333333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bAuUUnJ6oSKkJBCh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bAuUUnJ6oSKkJBCh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bAuUUnJ6oSKkJBCh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bAuUUnJ6oSKkJBCh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .cluster text{fill:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh .cluster span{color:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bAuUUnJ6oSKkJBCh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bAuUUnJ6oSKkJBCh rect.text{fill:none;stroke-width:0;}#mermaid-svg-bAuUUnJ6oSKkJBCh .icon-shape,#mermaid-svg-bAuUUnJ6oSKkJBCh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bAuUUnJ6oSKkJBCh .icon-shape p,#mermaid-svg-bAuUUnJ6oSKkJBCh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bAuUUnJ6oSKkJBCh .icon-shape .label rect,#mermaid-svg-bAuUUnJ6oSKkJBCh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bAuUUnJ6oSKkJBCh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bAuUUnJ6oSKkJBCh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bAuUUnJ6oSKkJBCh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 口径1:部件分解加总 ≈ 185.9 GiB
口径2:层单价加总 ≈ 178.0 GiB
口径3:分片事实总和 = 181.3 GiB
三套口径互差 2--4%:
量化系数与分类边界造成的差异
核对方法:
任何权重清单先做两套独立加总再确认
- 常见误解:官方配方的示例常写
--tensor-parallel-size 2,那是为更大显存的卡准备的,181.3 GiB 均分为两份是 90.6 GiB,放不进 80 GiB 的 A800。因此在 4×A800 上本套件采用TP=2 × PP=2的组合:先按张量维度各分一半,再按层成本把 45 个主层切成 24,21 两段,每卡约 46 GiB,才低于单卡显存上限。
3. 权重接线:软链接、inode 与空挂载事故
- 权重不随仓库分发,
setup.sh --models-dir是唯一的登记入口,其核心动作是把解析软链接之后的绝对路径写入.env的MODELS_DIR。之所以值得单独提供一个参数,原因在三种接线方式的差异中:
bash
# 方式 A(推荐):直接指向真实权重父目录,serve.sh 与 compose 均可用
./setup.sh --models-dir /data/weights/GLM-5.3-Flash-CYBERSECURITY-W4A16
# 方式 B:软链接入口(仅 serve.sh 可用,它启动前自己会解析)
ln -sfn /data/weights/GLM-5.3-Flash-CYBERSECURITY-W4A16 models/GLM-5.3-Flash-CYBERSECURITY-W4A16
# 方式 C:整个目录搬进来,再设 MODELS_DIR=./models
mv /data/weights/GLM-5.3-Flash-CYBERSECURITY-W4A16 models/
3.1 双启动路径一致性约束:由哪一层负责暴露路径差异
- 命令行能运行的配置,编排文件未必一致,这是部署工程中的常见问题。本套件没有依赖人工自觉,而是设置了三层检查:
- 配置物化优先 :所有可能造成路径分歧的决策(并行度、分段、上下文上限)都由
--profile直接写入.env。compose 无法执行 shell 逻辑,因此不向它传递逻辑,只传递结果; - 模板缺键告警 :
setup.sh逐键比对.env.example与.env,落后即报告「缺少 N 个新键」,避免升级后旧.env与新模板不一致; - PROFILE 漂移核对 :
.env记录当前声明的预设名,启动前逐项复核,不一致的键会逐项列出,避免依赖记忆判断当前预设。
#mermaid-svg-JHGONjk7xc7P7piz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JHGONjk7xc7P7piz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JHGONjk7xc7P7piz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JHGONjk7xc7P7piz .error-icon{fill:#552222;}#mermaid-svg-JHGONjk7xc7P7piz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JHGONjk7xc7P7piz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JHGONjk7xc7P7piz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JHGONjk7xc7P7piz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JHGONjk7xc7P7piz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JHGONjk7xc7P7piz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JHGONjk7xc7P7piz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JHGONjk7xc7P7piz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JHGONjk7xc7P7piz .marker.cross{stroke:#333333;}#mermaid-svg-JHGONjk7xc7P7piz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JHGONjk7xc7P7piz p{margin:0;}#mermaid-svg-JHGONjk7xc7P7piz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JHGONjk7xc7P7piz .cluster-label text{fill:#333;}#mermaid-svg-JHGONjk7xc7P7piz .cluster-label span{color:#333;}#mermaid-svg-JHGONjk7xc7P7piz .cluster-label span p{background-color:transparent;}#mermaid-svg-JHGONjk7xc7P7piz .label text,#mermaid-svg-JHGONjk7xc7P7piz span{fill:#333;color:#333;}#mermaid-svg-JHGONjk7xc7P7piz .node rect,#mermaid-svg-JHGONjk7xc7P7piz .node circle,#mermaid-svg-JHGONjk7xc7P7piz .node ellipse,#mermaid-svg-JHGONjk7xc7P7piz .node polygon,#mermaid-svg-JHGONjk7xc7P7piz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JHGONjk7xc7P7piz .rough-node .label text,#mermaid-svg-JHGONjk7xc7P7piz .node .label text,#mermaid-svg-JHGONjk7xc7P7piz .image-shape .label,#mermaid-svg-JHGONjk7xc7P7piz .icon-shape .label{text-anchor:middle;}#mermaid-svg-JHGONjk7xc7P7piz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JHGONjk7xc7P7piz .rough-node .label,#mermaid-svg-JHGONjk7xc7P7piz .node .label,#mermaid-svg-JHGONjk7xc7P7piz .image-shape .label,#mermaid-svg-JHGONjk7xc7P7piz .icon-shape .label{text-align:center;}#mermaid-svg-JHGONjk7xc7P7piz .node.clickable{cursor:pointer;}#mermaid-svg-JHGONjk7xc7P7piz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JHGONjk7xc7P7piz .arrowheadPath{fill:#333333;}#mermaid-svg-JHGONjk7xc7P7piz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JHGONjk7xc7P7piz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JHGONjk7xc7P7piz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JHGONjk7xc7P7piz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JHGONjk7xc7P7piz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JHGONjk7xc7P7piz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JHGONjk7xc7P7piz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JHGONjk7xc7P7piz .cluster text{fill:#333;}#mermaid-svg-JHGONjk7xc7P7piz .cluster span{color:#333;}#mermaid-svg-JHGONjk7xc7P7piz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JHGONjk7xc7P7piz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JHGONjk7xc7P7piz rect.text{fill:none;stroke-width:0;}#mermaid-svg-JHGONjk7xc7P7piz .icon-shape,#mermaid-svg-JHGONjk7xc7P7piz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JHGONjk7xc7P7piz .icon-shape p,#mermaid-svg-JHGONjk7xc7P7piz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JHGONjk7xc7P7piz .icon-shape .label rect,#mermaid-svg-JHGONjk7xc7P7piz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JHGONjk7xc7P7piz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JHGONjk7xc7P7piz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JHGONjk7xc7P7piz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} setup 生成/升级
source / 内插
内插
检查
检查
.env.example(入库模板)
.env(机器本地)
serve.sh:docker run + 参数
引擎实例
docker-compose.yml:变量内插
三层守卫:模板缺键告警 / PROFILE 漂移核对 /(04 篇)check-compose
serve.sh负责解析、回退与自愈,compose 负责按配置原样执行,检查链负责发现两者最终结果不一致。- 容器内的挂载路径固定:权重以只读方式挂载到
/models,MODEL_PATH=/models/GLM-5.3-Flash-CYBERSECURITY-W4A16,:ro表示服务不会写入权重。目录名需与MODEL_NAME保持一致,两者一起修改也可以。
4. 页缓存预热:157 秒的收益
| 存储状态 | 读速 | 期间备注 |
|---|---|---|
| 冷(NFS 通路) | 0.565 GB/s | 单流协议解析与往返开销主导 |
| 热读(页缓存,warm 后实测) | 4.8--5.4 GB/s | 多流并发读时还能到 ~2.8 GB/s 的保守档 |
| 脚本判热阈值 | 1.5 GB/s | 先对单个分片整读计时,未命中才预热 |
warm_cache.sh的实现只有三步:判断冷热 (选取最大分片执行dd if=... of=/dev/null bs=4M,计时换算 GB/s,超过阈值即直接退出);并发预读 (find获取分片列表,xargs -P 16并发顺序读);汇报(总 GiB 除以耗时,给出预热前后对照)。其收益来自一条确定的 I/O 路径:
#mermaid-svg-51XaYTCQGzu4CS0P{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-51XaYTCQGzu4CS0P .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-51XaYTCQGzu4CS0P .error-icon{fill:#552222;}#mermaid-svg-51XaYTCQGzu4CS0P .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-51XaYTCQGzu4CS0P .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-51XaYTCQGzu4CS0P .marker{fill:#333333;stroke:#333333;}#mermaid-svg-51XaYTCQGzu4CS0P .marker.cross{stroke:#333333;}#mermaid-svg-51XaYTCQGzu4CS0P svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-51XaYTCQGzu4CS0P p{margin:0;}#mermaid-svg-51XaYTCQGzu4CS0P .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-51XaYTCQGzu4CS0P .cluster-label text{fill:#333;}#mermaid-svg-51XaYTCQGzu4CS0P .cluster-label span{color:#333;}#mermaid-svg-51XaYTCQGzu4CS0P .cluster-label span p{background-color:transparent;}#mermaid-svg-51XaYTCQGzu4CS0P .label text,#mermaid-svg-51XaYTCQGzu4CS0P span{fill:#333;color:#333;}#mermaid-svg-51XaYTCQGzu4CS0P .node rect,#mermaid-svg-51XaYTCQGzu4CS0P .node circle,#mermaid-svg-51XaYTCQGzu4CS0P .node ellipse,#mermaid-svg-51XaYTCQGzu4CS0P .node polygon,#mermaid-svg-51XaYTCQGzu4CS0P .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-51XaYTCQGzu4CS0P .rough-node .label text,#mermaid-svg-51XaYTCQGzu4CS0P .node .label text,#mermaid-svg-51XaYTCQGzu4CS0P .image-shape .label,#mermaid-svg-51XaYTCQGzu4CS0P .icon-shape .label{text-anchor:middle;}#mermaid-svg-51XaYTCQGzu4CS0P .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-51XaYTCQGzu4CS0P .rough-node .label,#mermaid-svg-51XaYTCQGzu4CS0P .node .label,#mermaid-svg-51XaYTCQGzu4CS0P .image-shape .label,#mermaid-svg-51XaYTCQGzu4CS0P .icon-shape .label{text-align:center;}#mermaid-svg-51XaYTCQGzu4CS0P .node.clickable{cursor:pointer;}#mermaid-svg-51XaYTCQGzu4CS0P .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-51XaYTCQGzu4CS0P .arrowheadPath{fill:#333333;}#mermaid-svg-51XaYTCQGzu4CS0P .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-51XaYTCQGzu4CS0P .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-51XaYTCQGzu4CS0P .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-51XaYTCQGzu4CS0P .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-51XaYTCQGzu4CS0P .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-51XaYTCQGzu4CS0P .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-51XaYTCQGzu4CS0P .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-51XaYTCQGzu4CS0P .cluster text{fill:#333;}#mermaid-svg-51XaYTCQGzu4CS0P .cluster span{color:#333;}#mermaid-svg-51XaYTCQGzu4CS0P div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-51XaYTCQGzu4CS0P .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-51XaYTCQGzu4CS0P rect.text{fill:none;stroke-width:0;}#mermaid-svg-51XaYTCQGzu4CS0P .icon-shape,#mermaid-svg-51XaYTCQGzu4CS0P .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-51XaYTCQGzu4CS0P .icon-shape p,#mermaid-svg-51XaYTCQGzu4CS0P .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-51XaYTCQGzu4CS0P .icon-shape .label rect,#mermaid-svg-51XaYTCQGzu4CS0P .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-51XaYTCQGzu4CS0P .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-51XaYTCQGzu4CS0P .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-51XaYTCQGzu4CS0P :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 冷读 0.565 GB/s,21 分钟量级
权重 181.3 GiB
宿主侧 dd 顺序读
内核页缓存(page cache)
全局资源,一次预热多方受益
容器 bind mount
同一 inode ⇒ 同一批常驻物理页
引擎加载接近内存读速度
未预热路径
- 宿主预热之所以对容器有效,原因在 VFS 语义:bind mount 使宿主与容器读取同一文件时命中同一批物理页,而 Linux 的页缓存不区分命名空间。
- 预热收益还需考虑并行维度:
TP=4时每个 rank 都要读取完整的 181.3 GiB checkpoint,总物理 I/O 约 728 GiB。两种读速分别代入:
bash
冷读:728 GiB ÷ 0.565 GB/s ≈ 1,288 s ≈ 21.5 分钟
热读:728 GiB ÷ 4.8--5.4 GB/s ≈ 135--152 s
- 预热的收益只影响总时长中的 I/O 部分。后续的 safetensors 反序列化与设备拷贝属于 CPU 密集阶段。把「权重加载 228--293 s」拆成 I/O(热路径 60--92 s)与反序列化(其余部分)两部分,可以得到两种不同的优化视角:前者是带宽问题,后者是计算问题。若把两者混为一谈,就无法设计出正确的预热策略。
4.1 并发度选择
-
脚本头部注释给出两个关键实测值:单流冷读 NFS 0.565 GB/s,多流约 2.8 GB/s。五倍差距的原因是单流带宽受往返时延与队列深度限制 ,必须等待上一笔读完成才能发起下一笔,管道长期处于半空状态;多路并发(脚本默认为 12 路,可用
WARM_PARALLEL提高)增加在途请求数,使 I/O 持续饱和。继续增加并发后收益进入平台期,此时的限制因素是介质本身的顺序读吞吐。这也是每路坚持bs=4M大块顺序读的原因:顺序被打乱时,增加 NFS 并发不会提高吞吐。 -
判热阈值 1.5 GB/s 的取值依据同样明确:它明显高于冷读(0.565)而远低于热读下限(2.8 起步),为介质抖动留出双向余量,即由两侧实测值夹出阈值。
5. 首次启动:376 秒的分阶段记录
- 执行
./serve.sh后,启动过程由若干可核对的里程碑组成,而不是一段无法区分的等待:
wait_ready.sh vLLM 容器 serve.sh 你 wait_ready.sh vLLM 容器 serve.sh 你 #mermaid-svg-1geoOU2RhqhoZ7C7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1geoOU2RhqhoZ7C7 .error-icon{fill:#552222;}#mermaid-svg-1geoOU2RhqhoZ7C7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1geoOU2RhqhoZ7C7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1geoOU2RhqhoZ7C7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1geoOU2RhqhoZ7C7 .marker.cross{stroke:#333333;}#mermaid-svg-1geoOU2RhqhoZ7C7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1geoOU2RhqhoZ7C7 p{margin:0;}#mermaid-svg-1geoOU2RhqhoZ7C7 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1geoOU2RhqhoZ7C7 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-1geoOU2RhqhoZ7C7 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-1geoOU2RhqhoZ7C7 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-1geoOU2RhqhoZ7C7 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-1geoOU2RhqhoZ7C7 .sequenceNumber{fill:white;}#mermaid-svg-1geoOU2RhqhoZ7C7 #sequencenumber{fill:#333;}#mermaid-svg-1geoOU2RhqhoZ7C7 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-1geoOU2RhqhoZ7C7 .messageText{fill:#333;stroke:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1geoOU2RhqhoZ7C7 .labelText,#mermaid-svg-1geoOU2RhqhoZ7C7 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .loopText,#mermaid-svg-1geoOU2RhqhoZ7C7 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-1geoOU2RhqhoZ7C7 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-1geoOU2RhqhoZ7C7 .noteText,#mermaid-svg-1geoOU2RhqhoZ7C7 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-1geoOU2RhqhoZ7C7 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1geoOU2RhqhoZ7C7 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1geoOU2RhqhoZ7C7 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-1geoOU2RhqhoZ7C7 .actorPopupMenu{position:absolute;}#mermaid-svg-1geoOU2RhqhoZ7C7 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-1geoOU2RhqhoZ7C7 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-1geoOU2RhqhoZ7C7 .actor-man circle,#mermaid-svg-1geoOU2RhqhoZ7C7 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-1geoOU2RhqhoZ7C7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ./serve.sh(或 docker compose up -d) 配置挂载与参数,docker run --gpus 权重加载(页缓存热 228--245 s) 打印 Available KV cache memory init engine:JIT 编译与加载(热 31--36 s,冷 182 s) ./wait_ready.sh 每 15 s 探一次 /health 首次调用 /v1/chat/completions 验收
- 启动里程碑的实测分组:
| 里程碑 | 首次(cache/ 无该并行度产物) | 热重启(页缓存 + JIT 全热) |
|---|---|---|
| 权重加载(每卡 46.03 GiB) | 261--293 s | 228--245 s |
| init engine ... took | 182.09 s | 31.5--36.1 s |
| ./serve.sh 到就绪 | 520 s | 376 s |
- 第一层结论:权重加载在两种场景只相差约 15%,而 init engine 相差 5.5 倍,初始化时间的方差主要来自编译,而不是权重搬运 。因此两项优化的性质不同:
warm_cache.sh减少的是 I/O 长尾(是否需要取决于 NFS 是否在路径上),cache/减少的是确定性等待(每次约省 150 s,且只要不改变并行度就始终有效)。 - 第二层结论在权重加载时间内部。粗算:181.3 GiB 在热页缓存上以 2.8 GB/s 计算只需约 65 s(仓库另一口径的同类实测为 60--92 s),剩余 160+ s 用于 safetensors 反序列化与设备拷贝,这部分是 CPU 密集型。仅优化 I/O 无法把启动时间压到一分钟以内,反序列化取决于整机 CPU 资源的分配。
5.1 就绪:日志三类常见信息
- 在
Application startup complete出现之后、第一批真实请求到来之前,日志中通常会出现以下三类信息,需要提前了解:
- 采样默认值的合并结果(WARNING,属预期) :引擎提示「Default vLLM sampling parameters have been overridden by the model's
generation_config.json」。这条日志打印的是合并后的最终值 ,因此可以直接拿它核对配置是否生效------当前输出的是{'repetition_penalty': 1.0, 'temperature': 0.3, 'top_k': 20, 'top_p': 0.95}。若这四项留空,打印的才是权重自带的1.1 / 1.0 / 0.95。 - KV 池容量报告 :
Available KV cache memory与GPU KV cache size两行给出显存分配的最终结果(部署形态二TP=4×PP=1热重启为 16 GiB / 1,320,553 tokens)。 - 离线模式 :
HF_HUB_OFFLINE=1随容器注入,权重与 tokenizer 的解析完全在本地进行,不会因网络请求影响启动时间。
- 就绪的最终判据是
/health返回 200(wait_ready.sh的职责)。就绪后的最初几分钟可以查看 waiting/running 队列日志,确认引擎已开始处理请求。
wait_ready.sh 的退出码定义如下:
| 退出码 | 含义 | 附注 |
|---|---|---|
| 0 | READY | /health 200 |
| 1 | TIMEOUT | 默认 3600 s,可用 WAIT_TIMEOUT_S 覆盖 |
| 2 | 容器缺失或已退出 | 打印 docker logs 末尾若干行以便定位 |
- 探活接口的选择在仓库中有明确结论:
/health是权威的存活信号(引擎异常时返回 5xx),而/v1/models在引擎已停止响应时也可能返回 200。
最后用一次实际调用验证服务:
bash
curl -s http://127.0.0.1:18007/health # 返回 200 表示引擎健康
curl -s http://127.0.0.1:18007/v1/chat/completions \
-H 'Content-Type: application/json' -d '{
"model": "glm-5.3-flash-cybersec-w4a16",
"messages": [{"role": "user", "content": "用一句话介绍你自己"}],
"max_tokens": 600,
"chat_template_kwargs": {"reasoning_effort": "high"}}'
reasoning_effort: high 的取值原因是:官方模板的 max 档思考过程很长,max_tokens 设置过小会出现 finish_reason=length 且正文为空的情况。本套件在请求示例中显式使用 high 档,模板相关配置见 .env.example 中的 GLM_CHAT_TEMPLATE。