LLM Infer Infra 学习资料库

实测与故障演练:测什么、怎么测、怎样记录

实验主题 · GPU 与 kernel 基础 · 设计图册 · 专家面试总纲

资料里的数字都是推导或公开数据,不是你的实测。第 2 节整理了常见硬件和项目的公开数据,可以先用来估算。面试时,能拿出自己测过的数据和做过的故障演练,比背公式有说服力得多。这一页给出测什么、怎么测、记什么、怎样算通过,结果需要你在真实环境里填写。

安全提醒:所有压测和故障注入只在独立的测试环境中进行。不要在生产集群上杀进程、断网或清空缓存。

1. 先记录环境

没有环境信息的数字无法比较。每次实验先填这张表:

项目怎么查记录
GPU 型号、数量、驱动、CUDAnvidia-smi
GPU 与网卡拓扑nvidia-smi topo -m
PCIe 代数与宽度nvidia-smi -q 中的 PCIe 信息,或 lspci -vv
RDMA 网卡与端口状态ibv_devinfo
NUMA 布局numactl --hardware
软件版本引擎、LMCache、Mooncake 的版本或 commit
模型与 KV 配置模型 revision、dtype、KV dtype、TP/PP、block/chunk 大小

2. 常见场景的公开参考数据

没有自己的测量数据时,可以先用公开规格和公开测试结果做估算,等有环境后再用实测替换。下面的数字分三类,引用时要说清是哪一类:厂商规格(理论峰值)、常见实测量级(公开测试中经常看到的范围,具体平台差异大)、项目公开结果(某个项目在特定配置下报告的数据)。

2.1 GPU 显存带宽与算力(厂商规格)

GPU显存显存带宽BF16 稠密算力平衡点(算力 ÷ 带宽)GPU 间互连主机接口
A100 80GB SXM80 GB HBM2e约 2.0 TB/s约 312 TFLOPS约 153 FLOP/byteNVLink 600 GB/sPCIe Gen4
H100 SXM80 GB HBM3约 3.35 TB/s约 989 TFLOPS约 295 FLOP/byteNVLink 900 GB/sPCIe Gen5
H200 SXM141 GB HBM3e约 4.8 TB/s约 989 TFLOPS约 206 FLOP/byteNVLink 900 GB/sPCIe Gen5

说明:算力是不含稀疏加速的稠密 BF16 值;NVLink 带宽是双向合计。用这些数字推出的 Decode 下界(以资料示例模型为例):

估算项A100H100H200
8B 模型 BF16 权重(16 GB)每步读一遍约 7.8 ms约 4.8 ms约 3.3 ms
一个 8K 上下文请求每步读一遍 KV(1 GiB)约 0.53 ms约 0.32 ms约 0.22 ms

这些是只考虑显存带宽的理论下界,实际还有 kernel 效率、调度和通信开销。原理见 GPU 与 kernel 基础。

2.2 PCIe 与 RDMA 网卡

链路理论带宽(每方向)常见实测量级传 1 GiB 约需
PCIe Gen4 x16(锁页内存 H2D)约 32 GB/s约 24–26 GB/s约 41–45 ms
PCIe Gen5 x16(锁页内存 H2D)约 64 GB/s约 50–55 GB/s约 20–22 ms
200 Gb/s 网卡(如 HDR IB、200GbE RoCE)25 GB/s大消息 ib_write_bw 常见约 23–24 GB/s约 45–47 ms
400 Gb/s 网卡(如 NDR IB、400GbE RoCE)50 GB/s大消息 ib_write_bw 常见约 46–48 GB/s约 22–23 ms

2.3 项目公开结果

来源场景与配置报告结果怎样理解
Mooncake README传输 40 GB 数据(相当于 LLaMA3-70B 128K token 的 KV),4×200 Gbps RoCE约 87 GB/s,约为 TCP 的 2.4 倍线速合计 100 GB/s,利用率约 87%
同上同样数据,8×400 Gbps RoCE约 190 GB/s,约为 TCP 的 4.6 倍线速合计 400 GB/s,利用率约 48%;网卡越多,越难线性扩展
Transfer Engine 文档transfer_engine_bench 示例运行,持续 10 秒约 19.87 GiB/s文档注明超过了该主机单卡的最大吞吐(使用了多卡)
Mooncake README 引用的 Kimi K2 部署128 张 H200,PD 分离 + 大规模专家并行Prefill 约 22.4 万 token/s,Decode 约 28.8 万 token/s(集群合计)是整套部署的结果,不能直接归因于某一个组件

核对一下第一行:LLaMA3-70B 是 80 层、8 个 KV head、head 维度 128,BF16 下每 token 2 × 80 × 8 × 128 × 2 = 320 KiB,128K token 正好 40 GiB(约 43 GB),和 README 写的“40 GB”是同一量级,README 用的是十进制口径。按 87 GB/s 传完约需 0.49 秒,按 190 GB/s 约 0.23 秒。

2.4 用公开数据做一次完整估算

场景:LLaMA3-70B 级别模型,8 张 H100,一个 32K token 的共享前缀被远端命中。

KV 大小:320 KiB × 32,768 ≈ 10 GiB(约 10.7 GB)

加载(串行估算):
  单张 400G 网卡按 46 GB/s:10.7 ÷ 46 ≈ 0.23 s
  若 8 张 GPU 各自用 Gen5 H2D 并行接收,每张约 1.34 GB,按 50 GB/s:≈ 0.03 s
  再加查询和同步的固定开销,合计约 0.3 s 量级

重算 Prefill:
  主体计算 ≈ 2 × 70e9 × 32,768 ≈ 4.6e15 FLOP
  8 × 989 TFLOPS × 50% 利用率 ≈ 4.0e15 FLOP/s
  ≈ 1.2 s(未计入注意力项,长上下文下实际更长)

结论:在这些假设下,远端加载明显比重算快。

换成 1K token 的短前缀,KV 只有约 0.3 GiB,重算只要几十毫秒,查询和网络的固定开销占比就变大,收益会缩小甚至变负。可以把这些公开数字填进互动盈亏计算器试试。有了自己的环境后,按下一节逐层实测,替换这里的公开数字。

3. 分层测量:从硬件到端到端

按从下到上的顺序测。每一层的结果解释上一层:端到端慢了,先看是不是某一层本身就达不到预期。

3.1 H2D 与 D2H 带宽

目的:确认 CPU↔GPU 拷贝的实际带宽,比较锁页内存与可分页内存。

import torch

size = 1 << 30  # 1 GiB
for pinned in (True, False):
    host = torch.empty(size, dtype=torch.uint8, pin_memory=pinned)
    dev = torch.empty(size, dtype=torch.uint8, device="cuda")
    for _ in range(3):
        dev.copy_(host, non_blocking=True)
    torch.cuda.synchronize()
    start = torch.cuda.Event(enable_timing=True)
    end = torch.cuda.Event(enable_timing=True)
    start.record()
    for _ in range(10):
        dev.copy_(host, non_blocking=True)
    end.record()
    torch.cuda.synchronize()
    gib_s = 10 * size / 2**30 / (start.elapsed_time(end) / 1000)
    print(f"pinned={pinned}: H2D {gib_s:.1f} GiB/s")

记录:两种内存的 H2D、D2H 带宽;GPU 编号与所在 NUMA。通过标准:锁页内存接近该 PCIe 代数的常见实际值(Gen4 约 25 GB/s,Gen5 约 50 GB/s);明显偏低时检查拓扑和 NUMA 绑定。

3.2 RDMA 链路带宽

目的:确认两台机器之间网卡的实际带宽,排除网络配置问题。

# 服务端
ib_write_bw -d <设备名> --report_gbits
# 客户端
ib_write_bw -d <设备名> --report_gbits <服务端地址>

ib_write_bw 来自 perftest 工具包。记录:不同消息大小下的带宽和延迟。通过标准:大消息带宽接近网卡线速的合理比例;小消息延迟稳定。

3.3 Transfer Engine 吞吐

目的:在 Mooncake TE 层测量读写吞吐,看软件层相对裸链路损失了多少。Mooncake 编译后提供 transfer_engine_bench:先以 --mode=target 启动目标节点,再在发起节点指定 --segment_id 运行;可调 --operation(read/write)、--block_size、--batch_size、--threads、--duration。完整参数见 Transfer Engine 文档。

记录:block 大小从 64 KiB 到 64 MiB 的吞吐曲线;线程数与吞吐的关系。重点观察:小 block 时吞吐下降多少——这决定了 KV 对象(chunk × rank)不宜太小。

3.4 Store 读写与加载链路

目的:测量一次完整的对象写入和读取(含元数据查询),再测 LMCache 从远端加载到 GPU 的时间分解。

记录:对象大小、并发数下的 put/get 延迟分布(P50/P99);加载链路中查询、远端读、H2D 各段耗时。通过标准:能说清每段耗时占比,并与 互动盈亏计算器的估算对比,解释差距来源。

3.5 端到端服务

目的:在相同负载下比较“不开缓存 / 只开本地缓存 / 开远端缓存”三种配置。可用引擎自带的压测工具(例如 vllm bench serve)。

记录:TTFT、ITL 的分布,吞吐,goodput,实际少算的 token 数,远端读取字节数。通过标准:结论注明负载(前缀共享率、长度分布、到达率),并包含至少一个缓存“不划算”的对照场景。

4. 故障演练

每个演练都按“预期 → 注入 → 观察 → 恢复 → 结论”记录。重点不是证明系统不出错,而是确认出错时不产生错误输出、资源最终能回收、服务能按预期降级。

演练怎么注入(测试环境)预期行为要观察的指标
存储节点退出停止一个贡献 segment 的进程相关读取失败并回到重算;有副本时改读其他副本;不出现错误输出miss 原因、重算速率、TTFT 变化、错误输出数(应为 0)
目录主节点切换停止主节点,观察 HA 切换切换期间查询按 miss 处理;恢复后旧位置失效;服务限流预热切换耗时、恢复期 SLO、命中率回升曲线
网络变慢在测试机上注入延迟或限速加载超时后隔离目标并重算;超时任务最终完成或取消超时数、隔离中的 buffer 数、内存是否回落
租约过期在读取路径人为增加排队延迟,超过租约时长完成后检测到过期并拒绝数据过期拒绝次数、是否有数据被误用
请求取消加载进行中取消请求不立即复用目标页;底层完成后再释放迟到回调是否被丢弃、显存与 host 内存是否泄漏
缓存全冷清空测试缓存后施加正常负载GPU 承担全部 Prefill;按优先级准入或限流GPU 队列、拒绝率、恢复到基线的时间
格式不匹配用不同 KV dtype 或模型版本的实例读取同一命名空间因身份或格式不同而不命中,或校验失败后拒绝错误输出数(应为 0)

正确性检查方法:固定随机种子和贪心解码,比较开缓存与关缓存时的输出;或比较 logits 差异在数值误差范围内。任何一次输出不一致都要当作严重问题追查。

5. 结果记录模板

实验名称:
日期 / 执行人:
环境:(引用第 1 节表格)
假设:例如“远端加载 8K 前缀比重算快 50% 以上”
配置:负载、并发、缓存配置、对照组
结果:原始数据位置、关键数字(含 P50/P99)
与估算的差距:差多少,原因是什么
结论:假设成立 / 不成立 / 有条件成立
未验证项与后续:

把三份以上这样的记录整理进面试材料,就能回答“你怎么证明”的追问。

输入主题、术语或问题