先摸清专家路由与批大小——再看 Hy3 能扛多少并发

文章导读
并发一上去延迟就抖,先别急着改批大小或专家切分。专家路由决定了单卡要加载和计算哪些专家,批大小决定了每次前向传播的 token 数和激活显存;两者耦合在一起,任何单参数调整都可能把瓶颈从计算推到显存或通信。要判断 Hy3 能扛多少并发,需要先确认当前配置把专家放在了哪里,再用逐级加压的方式记录排队延迟与单步计算延迟,最后用可复现的停机线界定上限。
📋 目录
  1. 壹 在配置里确认专家切分方式与单卡承载的专家数
  2. 贰 用逐级加压脚本记录延迟、吞吐与显存峰值
  3. 叁 从服务日志区分排队延迟与单步计算延迟
  4. 肆 调整批大小与最大并发两个参数做单变量对照
  5. 伍 给出并发上限的判定口径和超限后的表现
A A

并发一上去延迟就抖,先别急着改批大小或专家切分。专家路由决定了单卡要加载和计算哪些专家,批大小决定了每次前向传播的 token 数和激活显存;两者耦合在一起,任何单参数调整都可能把瓶颈从计算推到显存或通信。要判断 Hy3 能扛多少并发,需要先确认当前配置把专家放在了哪里,再用逐级加压的方式记录排队延迟与单步计算延迟,最后用可复现的停机线界定上限。

专家切分和批大小共同影响 Hy3 的并发能力:专家并行度高则单卡专家数少、显存压力小,但路由通信可能增加;批大小增大会提高计算利用率,也会同步推高激活显存和单步延迟。建议先固定一个变量,从并发 1 开始逐级加压,记录 P99 延迟、吞吐、显存峰值和错误数,以延迟翻倍、错误率非零、显存逼近上限作为停机线。不同硬件和请求长度下上限不同,需以实际日志和监控为准。

在配置里确认专家切分方式与单卡承载的专家数

先找到服务启动配置或推理框架的并行配置。不同框架命名不同,以下为占位示例,需要替换成实际字段名。

# 示例:专家并行与张量并行配置占位
model:
  num_experts: 8
  expert_parallel_size: 2
  tensor_parallel_size: 4
  expert_parallel_degree: 2   # 有些框架用这个字段
  max_batch_size: 16

expert_parallel_size 或 expert_parallel_degree 决定专家分片到多少张卡;tensor_parallel_size 决定每个专家内部的计算切分。单卡承载的专家数通常等于 num_experts 除以 expert_parallel_size(如果专家均匀分布),但路由可能让某些卡承担更多 token。改动后显存分布的变化方向:增大专家并行度,单卡需要驻留的专家参数减少,显存占用通常下降,但跨卡路由通信可能增加;减小专家并行度则相反。上述变化需要以实际日志验证,例如启动日志中会打印每张卡的参数分布或专家放置信息,字段名可能是 expert_placement、per_rank_params 等,以实际框架为准。也可以同时用 nvidia-smi 观察各卡显存变化。

先摸清专家路由与批大小——再看 Hy3 能扛多少并发

用逐级加压脚本记录延迟、吞吐与显存峰值

不要凭单次请求的感受判断并发能力。建议写一个逐级加压脚本,并发从 1 开始,按 1、2、4、8、16、32 递增,直到触发停止判据。下面是一个命令骨架,压测工具可替换为 hey、wrk 或自研客户端。

#!/bin/bash
URL='http://127.0.0.1:8000/generate'
REQ='request.json'
for C in 1 2 4 8 16 32; do
  echo "concurrency=$C"
  # 开始记录显存峰值,例如后台采样 nvidia-smi
  nvidia-smi `--query-gpu`=memory.used `--format`=csv -l 1 > mem_$C.log &
  SAMPLER=$!
  # 压测命令骨架,-n 为总请求数,-c 为并发数
  hey -n 200 -c $C -m POST -T application/json -d @$REQ $URL > result_$C.txt
  kill $SAMPLER
  # 从 result_$C.txt 提取 P50/P99 延迟、吞吐、错误数
done

每次要记录的四个指标:P50/P99 延迟、吞吐(每秒完成请求数或 tokens 数)、显存峰值、错误数。停止加压的判据:P99 延迟超过低并发基线的两倍,或错误数从零开始上升,或显存峰值逼近单卡容量上限(例如剩余显存很少)。满足任意一条就停止,并记录前一级并发作为候选上限。注意每次压测前重启服务或确保状态干净,请求内容要覆盖实际长度分布。

从服务日志区分排队延迟与单步计算延迟

延迟抖动可能来自调度排队,也可能来自单步计算变慢。在服务端日志或指标中找两类耗时字段(不同框架命名不同,以下为占位):queue_wait_ms 或 request_queue_time、step_latency_ms 或 forward_time。观察方法一:固定批大小,只增加并发。如果 queue_wait 随并发线性上升,而 step_latency 基本不变,说明请求在排队,瓶颈在调度或并发处理能力。观察方法二:固定并发,只增加批大小。如果 queue_wait 很小但 step_latency 随批大小明显增加,说明单步计算是瓶颈。也可以看日志中每个请求的分解,例如:

先摸清专家路由与批大小——再看 Hy3 能扛多少并发
[request_id=xxx] queue_wait_ms=12.3 step_latency_ms=45.6 total_ms=57.9

注意字段名是占位,需要按实际服务替换。如果找不到现成字段,可以在客户端记录端到端延迟,同时用服务端日志的请求开始和结束时间戳做差,粗略区分。

调整批大小与最大并发两个参数做单变量对照

单变量对照的目的是确认哪个参数对延迟更敏感。建议顺序:先固定最大并发数(例如 1 或 2)和请求内容,只改变批大小 1、2、4、8,记录每次的 P99 延迟、吞吐和显存峰值;再固定批大小(例如 4),只改变最大并发数 1、2、4、8,记录同样指标。记录表可以用下面的格式:

先摸清专家路由与批大小——再看 Hy3 能扛多少并发
批大小最大并发P50延迟P99延迟吞吐显存峰值错误数
11
21
41
42
44

说明批大小增大时显存占用与延迟的双向变化:批大小增大,单次前向计算的 token 数增加,激活显存和 KV cache 通常同步增加;在计算单元未打满前,吞吐可能上升,延迟变化不大;超过计算容量后,单步计算时间线性增加,延迟明显上升。因此需要找到延迟开始显著上升的批大小,再结合最大并发数做取舍。

给出并发上限的判定口径和超限后的表现

为了让上限可复现,建议先定三条停机线。第一条,延迟翻倍:以单请求或低并发时的 P99 延迟为基线,当某一级并发的 P99 达到基线的两倍时,视为超限。对应日志特征:请求延迟日志中 P99 突增,或 queue_wait_ms 显著上升。第二条,错误率上升:出现超时、OOM、连接重置等错误。对应日志特征:服务日志出现 timeout、out of memory、CUDA error、connection reset 等关键字,或监控错误计数从零变为非零。第三条,显存逼近上限:显存峰值达到单卡容量的一定比例(例如 90% 或剩余不足 1GB),对应日志特征:nvidia-smi 显示显存接近上限,或服务日志出现内存分配失败、KV cache 不足等警告。超限后的表现包括:延迟抖动加剧、吞吐不再上升甚至下降、服务开始拒绝请求。判定口径:在固定硬件、配置、模型版本和请求分布下,按逐级加压步骤找到第一个触发停机线的并发数,该并发数减一即为可稳定运行的上限。上限会随请求长度和专家路由分布变化,建议在业务变更后复测。