资讯动态

GLM5.3 CyberSec w4A16本地部署[2]:并行策略与 PP 切分

发布时间:2026/10/20 10:52:43 来源:尧图企业网站定制
02 · 并行策略与 PP 切分GLM5.3 CyberSec W4A16权重地址部署仓库地址本篇讲并行策略怎么选MLA 模型上TP换不来 KV 容量、PP提升容量、PP_LAYER_PARTITION41,37层切分的来源以及DP/EP/DCP/PCP不使用的原因。文章目录02 · 并行策略与 PP 切分0. 结论1. 硬件与显存占用计算2. TP 对 KV 容量贡献是 03. PP按层切分容量 ≈ ×PP3.1 机制3.2 基于VLLM v0.30定制镜像4. 41,37PP 显存均衡的那笔账4.1 39,39 下卡 0-3 只用 70.7 GiB4.2 四档切分对照4.3 实测结果41,37 优于预测5. PP2 的正确性缺陷与「方案 B」5.1 机制DSA 的跨层索引共享被切分边界打断5.2 实测退化同口径 p5_identitysane 采样 temp0.8 / top_p0.95.3 修复方案 B5.4 修复后 PP2 全面优于 PP15.5 层切分与 gate 的耦合必须 preflight6. deploy.sh 里的 PP 缺省与门禁7. 其余维度不使用原因8. PP 层间通信与 NCCL9. 部署配置选择10. 复现命令0. 结论MLA 的 KV 在 TP rank 间完全复制--tensor-parallel-size对 KV 容量的贡献是0相关容量占用必须按单卡算。PP是唯一的扩容手段TP8/PP1338,688 →TP4/PP2791,744×2.34→TP2/PP41,193,600×3.52v0.30 定稿形态PP1386,943 →PP2 41,37729,280。41,37是把末级闲置显存换成 KV池 597,760 →729,28022.0%最紧余量 1,802 →2,479 MiB38%§4。PP2有一个真实的缺陷DSA 跨层 top-k 索引共享在切分边界错位 ⇒19~21% 退化PP1 为 0/120「方案 B」修复后0/200。PP2被check_pp_dsa_gate()硬拦PP4 关掉投机仍有20%退化开 MTP k3 为45%⇒1M 上下文今天不可用。其余并行维度都不采纳DCP 启动即断言失败、PCP 被 MTP full CUDA graph 阻断、DP 要 16 卡、EP−1.5%、--block-size容量中性。1. 硬件与显存占用计算nvidia-smi topo -m实测4 对 NVLink0↔1、2↔3、4↔5、6↔7NV8跨对 PCIe/SYSGPU 0-3 在 NUMA0、4-7 在 NUMA1。所以本机不是PCIe-only但跨对 all-reduce 很贵。kernel profile 给出的量级TP8 时代NCCL all-reduce 占 39.1%的窗口时间AllReduce 36.4% AllGather 2.4%每步156 次 all-reduce × 191 µs78 层 × 2其余是 DSA 注意力 23.1%、Marlin MoE 18.6%、bf16 GEMM 12.0%。这张表是后面所有并行取舍的地基通信量由哪些维度要跨卡同步决定。显存侧的三个基础事实每卡权重的口径是390.58 GiB / (TP × PP)Checkpoint size: 390.58 GiB启动日志weight_utils.py:858。TP×PP 恒为 8 时每卡 ≈48.8 GiB所以 PP 换来的是纯 KV 收益不是省权重。每 rank 的显存预算 gmu × 79.25 GiBgmu 0.95⇒75.29 GiB所有 rank 相同。TP×PP 必须 ≥ 8否则每卡权重 80 GiB 装不下TP4/PP1 是 97.5 GiB/卡。8 卡上就只剩 (8,1)、(4,2)、(2,4) 三种分法。KV 的每 token 记账fp8_ds_mla、TP8/PP1、block_size64实测反推、误差 0.22%主 attention 层:79层78 主干 1MTP×656Bfp8_ds_mla51,824B DSA indexer cache:21层indexer_typesfull ×132B2,772B 每 token/rank54,596Bblock_size64⇒ 每 block/rank3,494,144 B3.332 MiB338,688token ×54,596B17.222GiB ≤17.26GiB ✅1 GiB 显存 ≈ 19,668 token 的 KVDSA indexer cache 与主 KV 在同一个池里2. TP 对 KV 容量贡献是 0这是整套并行策略的起点值得把机制写清楚MLA 只有 1 个 KV 头num_kv_heads1mla_attention.py:1160-1169页大小公式是(head_size head_size_v) × dtype_size或state_content_bytes里面没有任何tensor_parallel_size项。池子大小按本 rank 的层数算num_blocks int(available_memory // page_size // num_layers)除的是num_layers而不是 TP。DSA indexer 的 k_cache 同样复制deepseek_v2.py:656的注释就是# no tensor parallel, just replicated。⇒每个 TP rank 都分配一份同样大的完整 MLA KV 池。启动日志里那句Maximum concurrency for 327,680 tokens per request: 1.04x就是这么来的。343,232 / (327,680/64) ≈ 1.047。所以加卡对上下文长度一点贡献都没有想扩 KV 只能换维度 层维PP或序列维DCP。DP 也不行每个 DP rank 各自一份完整模型与 KV 池单卡容量不变。3. PP按层切分容量 ≈ ×PP3.1 机制PP 把 78 层主干切成 PP 段每 rank 只建自己那段。KV spec 只从本 rank 的static_forward_context取。于是num_blocks公式里的num_layers变成L/PP而每请求 block 数不变 ⇒max_concurrency num_blocks / blocks_per_req≈ ×PP。细节所有 rank 的 block 数取最小值对齐“Change the num_blocks of each rank to the smallest among all ranks”。这既解释了为什么最紧的 stage 决定一切也解释了 78 不能被 4 整除19.5时为什么要用VLLM_PP_LAYER_PARTITION手动分。3.2 基于VLLM v0.30定制镜像形态GPU KV cache sizemax_model_len单流内容受控中位conc16TP8/PP1 MTP k3 fp8_ds_mla单流形态386,943352,000~68245.8TP4/PP241,37 MTP k3 fp8_ds_mla缺省729,280524,28871.3297~310按两列相除是≈1.88×386,943 → 729,280比 v0.28 时代的 2.34× 低是因为这一档同时带着 MTP—— 末 rank 多一个 MTP 层而它的 DSA indexer cache 也在这个 KV 池里v0.28 上同镜像 A/B 测过PP2 无投机791,744vs PP2 MTP623,168MTP 吃掉约21%的容量收益。这是容量换单流的取舍不是配置失误。PP解决的是每 token 占多少显存里的层数因子另一个因子是每层每 token 的字节数fp8_ds_mla656 B相对 bf161152 B的容量是×1.71343,232 / 200,704低于格式上限 ×1.756差额被两种配置下同样大的 DSA indexer cache 摊薄而bf16 的硬上限是 236,224 token。4.41,37PP 显存均衡的那笔账4.139,39下卡 0-3 只用 70.7 GiB实测TP4/PP2 MTP k3 gmu 0.95单位 GiB权重 非 torch峰值 activationCUDAGraph可用 KV实际分配 KV合计nvidia-smiPP0 卡 0-350.982.360.7621.9515.5669.6672,430 MiBPP1 卡 4-756.533.201.4915.56← 瓶颈15.5676.7880,118 MiB预算0.95 × 79.25 75.29 GiB两 rank 相同加上 0.93 GiB CUDA context 后与nvidia-smi逐项闭合到 ~0.2 GiB。根因链条PP0 层 0–38含 3 个 dense 层PP1 层 39–77 MTP 层 lm_head final norm外加 MTP 带来的更大 CUDA graph pool0.76 →1.49 GiB与更大峰值 activation。权重体积按 checkpoint 头实测MoE 层5,177.8 MiB/层MTP 层 5,339.7TP4⇒≈1.30 GiB/卡/层。反推 PP0 36×1,332.6 3×191 454 49,000 MiB与启动日志的 47.85 GiB 吻合。num_blocks min_r(可用KV_r / page_r)⇒ 池子被PP1 的 15.56 GiB卡死。卡 0-3 的 6.4 GiBvLLM 口径/ 8.7 GiBnvidia-smi口径在39,39下无法变成上下文。4.2 四档切分对照把 MoE 层从 PP1 挪到 PP0就是在把前一段的闲置显存换成瓶颈段的可用 KV切分瓶颈可用 KVKV 池预测单流算力层当量MTP×3gate 翻层39,39旧缺省15.56 GiB597,760实测39 vs42rank1: 39,40,4140,3816.86 GiB≈647,700 (8.4%)40 vs 41rank1: 40,4141,37★18.16 GiB≈697,600 (16.7%)41 vs 40rank1: 4142,3618.05 GiB≈693,300 (16.0%)42 vs 39无零依赖 gate★ 同时KV 最大且算力最均衡。末级每步要替 MTP 跑3 次前向所以现状39 vs 42末级本来就是流水线的 straggler挪走两层同时缓解了容量与算力两件事。4.3 实测结果41,37优于预测项39,3941,37变化GPU KV cache size597,760729,28022.0%优于预测的 16.7%524,288 单请求并发1.14×1.39×22%step_ms与内容无关34.1533.70−1.3%单流内容受控中位71.271.3相等噪声内agent 档退化0/400/40后加测 0/200保持质量探针 / Responses / 工具往返12/1212/12 / 10/10 / 20/20—nvidia-smi卡 0-3 / 卡 4-772,430 / 80,118 MiB79,441 / 79,343 MiB最紧余量 1,802 →2,479 MiB38%安全前置scripts/v030_pp_rebalance.sh preflightPASSrank1 区间[41,78)、自算层[42,46,…,74]、gate 需翻层[41]、新 gate 残余不安全 0反例45,33上旧式区间法漏判 1 层、新get_pp_indices()为 0 ⇒ 反例成立、不是恒真断言。5. PP2 的正确性缺陷与「方案 B」5.1 机制DSA 的跨层索引共享被切分边界打断本模型 DSA 配置index_topk_freq4index_skip_topk_offset3⇒只有层 2, 6, 10, …, 38, 42, …, 74 自己计算 top-k 索引其余层复用最近一次自算的共享缓冲。PP2按39,39切rank0 层 0–38rank1 层 39–77而rank1 的第一个自算层是 42⇒ rank1 上的39/40/41 三层复用了本 rank 从未写入过的缓冲首轮未初始化之后是上一轮遗留的陈旧索引⇒ 3/39 层注意力错误。PP1 免疫因为共享链在同一个 rank 内是完整的。诊断性的根因验证开关HF_OVERRIDES{index_topk_freq:1}把跨层共享整个关掉每层自算代价是 indexer 计算量 ×4。5.2 实测退化同口径p5_identitysane 采样temp0.8 / top_p0.9栈退化率PP1 MRV1 MTP0/40 0%✅PP1 MRV2 MTP0/120 0%✅PP2 MRV2 MTP21/100 21%❌PP2SPEC_METHODnone完全不投机19/100 19%❌失败形态很好认先答对再循环、从不发出 EOS一路打满 3000 token连正常样本的 token 中位都比 PP1 长2.3×84 vs 37。统计上 Fisher 单尾p 7.4e-09。⇒缺陷是PP1本身与投机解码、与 MRV2 都无关。5.3 修复方案 Bpatches/sm80_v030/pp_index_share_fix.pyfrag用get_pp_indices()取真实层区间强制本 rank 内没有索引可复用的那一层自算PP1 时判定恒为 False ⇒ 逐位兼容。修后p5_identity0/100完整验收0/200。5.4 修复后 PP2 全面优于 PP1指标旧定稿TP8/PP1TP4/PP2 方案 BGPU KV cache size386,943597,760×1.55max_model_len单请求上限352,000524,288×1.49单流纯解码71~81 tok/s85.6 tok/sconc4 / conc8 / conc16 聚合168.1 / 144.8 / 245.8179.3 / 190.7 / 312.327%p5_identity退化0/1200/1005 prompt 轮转退化N2000/2000/200长上下文寻针300K 3/3500K 3/3就绪654~670 s540 s能全面超过的原因有两条缺一不可上游 v0.30 在 MRV2 上真正实现了 PP 投机解码PPHandler.broadcast_drafts上游 #50514 / #46994 / #55745以及方案 B 把 19~21% 的退化消掉。前者让 PP 不再牺牲单流后者让 PP 的输出能用。5.5 层切分与 gate 的耦合必须 preflightrank0 永远不需要翻层层 0,1,2 本身就是自算层错位只发生在rank1 的开头。旧的手写rank*n//w区间式在39/40/41/42这四档上恰好也安全边界都落在两个自算层 38与42 之间但它是脆的45,33这类跨过自算层的切分会让层 45 去复用卡在 PP0 上的层 42 的索引 ⇒ 静默读未写入缓冲 ⇒ 退化复发。所以方案 B 改用get_pp_indices()。42,36是唯一的零依赖 gate档rank1 首层 42 本身就是自算层代价是算力 42 vs 39不如41,37的 41 vs 40 均衡。6.deploy.sh里的 PP 缺省与门禁脚本自己的变量是PP_LAYER_PARTITION/PP_SIZE/TP_SIZE其中层切分最终以VLLM_PP_LAYER_PARTITION注入容器。变量缺省形式作用TP_SIZE4--tensor-parallel-size张量并行度PP_SIZE2--pipeline-parallel-size仅 PP≠1 时加流水线并行度PP_LAYER_PARTITION41,37VLLM_PP_LAYER_PARTITION各 stage 层数DISABLE_CUSTOM_ALL_REDUCE0--disable-custom-all-reduceTP2含 PP4时必须开否则 graph profiling 阶段custom_all_reduce.cuh:164 invalid argument崩掉 EngineCoreALLOW_UNVERIFIED_PP0—PP2 的逃生舱FORCE_V2_RUNNER空按场景自动VLLM_USE_V2_MODEL_RUNNERPP1 自动 1门禁都在启动前跑./deploy.sh cmd预览时也会跑check_pp_dsa_gate()PP_SIZE 2直接die打印关掉投机仍 20%、开 MTP 45%与三条替代路径研究用途可ALLOW_UNVERIFIED_PP1放行放行时再警告一次并提示用完跑./deploy.sh degen。三条路径都已验证缺省 exit 0 / PP4 exit 1 / 逃生舱 exit 0 且带警告不是恒真断言。check_pp_layer_partition()段数必须 PP_SIZE、各段之和必须 78num_hidden_layers、只接受非负整数否则diePP_SIZE 1时只 warnvLLM 会忽略它。check_pp_mtp_compat()/check_pp_ngram_compat()按镜像版本判定vllm_supports_pp_spec()只在 0.30 为真。0.30 上 PP1 MTP 走 MRV2SPEC_METHODngram不在 MRV2 支持列表 ⇒ 直接die。resolve_defaults()自动选出的mtp在PP1 且镜像不支持 PPspec时降级为nonePP1 时自动钉VLLM_USE_V2_MODEL_RUNNER1因为 MRV2 对不支持的方法只会静默回退 MRV1而 MRV1 的 PP投机正是坏路径。缺省自证./deploy.sh defaultcheck逐项比对 argv含顺序与脚本会注入的每一个-e KEYVALUE有漂移即exit 2。7. 其余维度不使用原因维度flag容量乘数不采纳的原因DCPdecode context parallel--decode-context-parallel-size配置层×DCP本后端启动即断言失败TritonMLASparseImpl.can_return_lse_for_decode Falsev1/worker/cp_utils.py:47-54即便跳过断言mla_attention.py:953-976的assert lse is not None也过不去overlay 的forward_mqa显式return attn_out, Noneindex 本地化函数triton_filter_and_convert_dcp_index存在但本后端没调用过DCP 下会静默读错 KVindexer 的 DCP 合并只有 CuteDSL 版、注释写明首发面向 Blackwell/Hopper。尽调结论是15~25 人日且它与 fp8 补丁改同一个文件triton_mla_sparse_kernel.py同一容器路径只能挂一次⇒ 必须并进 fp8 的补丁链。详见05PCPprefill context parallel--prefill-context-parallel-size0官方注释就写明不增加 KV 分片数config/parallel.py:126-127还要额外占 GPU本机 8 卡没余量并被MTP full CUDA graph 双重阻断pcp_manager.py:125-162而且只支持 MRV2DP / 两个 TP4 实例--data-parallel-size单卡容量不变、只乘总吞吐需要16 卡8 卡做不到TP4 时每卡权重 97.5 GiB 80 GiB装不下EP专家并行--enable-expert-parallel与容量无关实测−1.5%无收益且必须同时选对--all2all-backend默认allgather_reducescatter不是真 all-to-all镜像里 pplx 未装--block-size加大—≈0分子分母抵消只影响尾部浪费/对齐且必须是64 的倍数--num-gpu-blocks-override—不凭空造显存填大了 OOM、填小了更少--kv-cache-memory-bytes—只是钉住 KV 字节数仍受物理显存上限DCP 与 PP 理论上正交一个切序列、一个切层乘数会相乘配置校验层也能过但在拿到 LSE 补丁前不要尝试。8. PP 层间通信与 NCCLPP 的通信是相邻 stage 之间的激活张量传递再加一条容易出事的小路径末 rank 把采样结果广播回其它 stage_pp_broadcast_prev_sampled_token_ids()—— v0.28 上PP1 MTP的第三层崩溃正是它该广播只在 async 下走、且只支持无投机的形状[num_reqs, 1]而带 MTP 时是[num_reqs, num_spec1]⇒ 直接断言失败。本项目测量过的通信大头是TP 的 all-reduce39.1%AllReduce 36.4% AllGather 2.4%的窗口时间、每步 156 次 × 191 µs —— 这些都是TP8/PP1形态的数字。改成TP4/PP2后all-reduce 的通信域缩到 stage 内的 4 卡、每 rank 层数减半同时 stage 之间多出一条点对点路径这两笔账的净量级我们没有单独 profile--disable-custom-all-reduce退回 NCCL 的性能代价也未单独测量。唯一确定的是NCCL 的三个旋钮NCCL_ALGOallreduce:tree/NCCL_PROTOLL128/NCCL_MIN/MAX_NCHANNELS1在 TP8 形态上全部负收益默认RING_LL已是最优。9. 部署配置选择约束布局KV 池单流内容受控中位conc16上下文正确性综合最优 ← 缺省TP4/PP241,37 MTP k3 fp8729,28071.3297~310512K✅ 0/200 · 12/12 · 工具往返 100/100单流优先旧缺省TP8/PP1 MTP k3 fp8386,943~68245.8352K✅ 0/120旧口径吞吐优先可选档TP4/PP241,37bf16KV458,56069.2363256K⚠️ 未做退化验收超长单请求1MTP2/PP420,20,20,181,199,872无投机64.0214.41M 20%无投机/ 45%MTP退化已被硬拦128K 并发的容量账池 729,280 ÷ (131,072 256) 5.55 ⇒ KV 允许5 条常驻实测 5/5、6/6 都被收下。但能收下 ≠ 更快长 prefill 会被调度串行化墙钟 ≈ 条数 × 50 sprefill 聚合吞吐恒定 ≈2,600 tok/s。一句话PP 是换容量的重量手段在 v0.30 上它恰好不再牺牲单流因为 MTP 在 PP 下也能工作了。10. 复现命令# ① 缺省 TP4/PP2 41,37 512K fp8 MTP k3与缺省自证./deploy.sh start ./deploy.shwait./deploy.sh cmd# 只看要拼出的命令行不启动./deploy.sh defaultcheck# argv 逐项 env 全部比对有漂移 exit 2# ② 回退/对照PP_LAYER_PARTITION39,39./deploy.sh start# 旧切分KV 597,760TP_SIZE8PP_SIZE1MAX_MODEL_LEN352000./deploy.sh start# 单流形态KV 386,943KV_CACHE_DTYPEbfloat16MAX_MODEL_LEN262144./deploy.sh start# 吞吐档conc16 ≈363# ③ 层切分的 gate 安全性与完整 A/Bpreflight 不动服务scripts/v030_pp_rebalance.sh preflight scripts/v030_pp_rebalance.sh control# 在当前切分上采基线scripts/v030_pp_rebalance.sh boot41,37# stop 换切分启动 启动门禁scripts/v030_pp_rebalance.sh verify# smoke / needle / degen / speed / qualityscripts/v030_pp_rebalance.sh verdict# 两支的显存·池·速度·退化对比表# ④ PP2默认被硬拦确认拦截与逃生舱行为PP_SIZE4TP_SIZE2./deploy.sh start# 期望 exit 1check_pp_dsa_gateALLOW_UNVERIFIED_PP1TP_SIZE2PP_SIZE4PP_LAYER_PARTITION20,20,20,18\MAX_MODEL_LEN1048576DISABLE_CUSTOM_ALL_REDUCE1./deploy.sh start# 研究用途警告放行# ⑤ 正确性判据PP 切分的真正验收线不是容量./deploy.sh degen# agent 档退化有退化 exit 2AGENT_PROBE_TRIALS200./deploy.sh degen# 收窄上界# ⑥ 根因诊断开关不是推荐配置关掉 DSA 跨层索引共享indexer 计算量 ×4HF_OVERRIDES{index_topk_freq:1}./deploy.sh start

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑