一、算子吞吐压测概述

大家好,我是你们的老朋友。今天咱们聊聊算子吞吐压测。

说实话,我刚入行那会儿,对「压测」这事儿挺不屑的。觉得模型能跑通就行,管它快不快呢?直到有一次,我负责的推荐系统上线,线上延迟直接飙到 200ms,用户反馈炸了锅……嗯,从那以后,我再也不敢轻视压测了。

1.1 什么是算子吞吐

先问个问题:你写了一个 Conv2d 算子,跑一遍 forward 用了 0.5 毫秒。这算快还是慢?

光看延迟,其实说明不了什么。你得看它「单位时间能处理多少数据」——这就是吞吐量。

算子吞吐,说白了就是:
一个算子在给定硬件上,每秒能处理多少个输入样本(或多少数据量)。

举个例子:
一个矩阵乘法算子,输入是 [1024, 1024] 的矩阵,在 A100 上跑一次耗时 0.1ms。
那它的吞吐就是 1 / 0.0001 = 10000 次/秒。

但注意,这只是单次推理的吞吐。实际压测时,我们通常用 batch 模式,一次喂进去一批数据,看总吞吐。

核心公式:
吞吐量 = 处理的数据量 / 总耗时
常用单位:samples/s、tokens/s、GB/s

1.2 为什么需要压测

我见过太多团队,模型在单卡上跑得飞快,一上多卡就崩。或者离线测试延迟 1ms,线上变成 10ms。

为什么会这样?

因为「能跑」和「能扛」是两码事。压测就是为了回答三个问题:

  • 这个算子到底能跑多快? —— 摸清硬件上限
  • 在多并发下会不会崩? —— 验证稳定性
  • 显存够不够用? —— 避免 OOM

我个人习惯,在开发新算子时,第一件事不是调精度,而是先压测。先知道它的性能天花板在哪,后面优化才有方向。

我的经验: 压测要趁早。等模型都训完了才发现算子慢,那改起来成本就高了。

1.3 压测的核心指标

压测不是只看一个数字。我一般会盯三个指标:

1. 吞吐量(Throughput)

这是最直观的指标。单位时间内能处理多少数据。

注意区分:

  • 峰值吞吐:理想状态下,硬件跑满时的最大吞吐
  • 实际吞吐:考虑数据搬运、kernel launch 开销后的真实吞吐

我曾经优化过一个 LayerNorm 算子,峰值吞吐能到 800GB/s,但实际跑起来只有 200GB/s。一查,发现是数据从 CPU 到 GPU 的拷贝成了瓶颈。嗯,这就是典型的「理论很丰满,现实很骨感」。

2. 延迟(Latency)

延迟和吞吐是跷跷板。你压得越狠,延迟往往越高。

我一般会看两个延迟:

  • P50 延迟:一半请求在这个时间内完成
  • P99 延迟:99% 的请求在这个时间内完成

为什么看 P99?因为 P50 好看,但 P99 才是用户体验的真相。我遇到过 P50 只有 2ms,但 P99 飙到 50ms 的情况——说白了,就是偶尔有请求被卡住了。

3. 显存占用(Memory Usage)

这个容易被忽略。很多新手只盯着吞吐和延迟,结果一跑大 batch 直接 OOM。

显存占用分两部分:

  • 静态显存:算子本身占用的参数、缓存
  • 动态显存:运行时临时分配的中间结果
避坑指南: 我曾经在压测一个 Attention 算子时,batch size 从 32 调到 64,吞吐没涨多少,显存却翻了一倍。后来发现是中间激活值占了大头。所以压测时一定要监控显存峰值,别等 OOM 了才后悔。

1.4 三个指标的关系

这三个指标不是孤立的。我画了张图,帮你理清它们的关系:

吞吐量 Throughput 延迟 Latency 显存占用 Memory batch↑ 延迟↑ batch↑ 显存↑ 显存↑ 延迟↑ 三者关系: 增大 batch → 吞吐↑ 但 延迟↑ 且 显存↑ 优化算子 → 吞吐↑ 且 延迟↓ 且 显存↓(理想情况) 压测的目标:找到三者之间的最佳平衡点

你看,这三个指标就像三根绳子拴在一起。你拉吞吐这根,延迟和显存也会跟着动。压测的目的,就是找到那个「既要马儿跑,又要马儿少吃草」的平衡点。

1.5 压测的基本流程

说了这么多,到底怎么压?我一般按这几步走:

  1. 确定压测目标:是测单算子,还是测整个模型?
  2. 选择压测工具:PyTorch Profiler、NVIDIA Nsight、还是自己写脚本?
  3. 设置压测参数:batch size、输入尺寸、数据类型(FP32/FP16)
  4. 运行并采集数据:至少跑 100 次,取稳定值
  5. 分析瓶颈:是计算瓶颈?访存瓶颈?还是通信瓶颈?
  6. 迭代优化:改完再测,直到达标
小技巧: 我习惯在压测前先跑一次 warmup,让 GPU 进入稳定状态。不然前几次的数据往往偏慢,容易误导。

1.6 常见误区

最后,分享几个我踩过的坑:

  • 只看平均延迟:平均延迟好看,但 P99 可能已经炸了。一定要看分布。
  • 忽略数据搬运:算子本身跑得再快,数据从 CPU 搬来搬去也白搭。
  • 一次压测就下结论:硬件有温度波动,多跑几次取中位数更靠谱。

好了,这一章就到这里。算子吞吐压测,说白了就是「用数据说话」。别凭感觉,别拍脑袋,跑一遍压测,什么都清楚了。

想要更多资料,联系可可