共计 2259 个字符,预计需要花费 6 分钟才能阅读完成。
为什么需要 AI 基准测试?
最近接手了一个图像分类项目,模型在测试集上准确率高达 95%,但上线后请求延迟超过 2 秒,直接被业务方打回。排查发现测试时用的都是 256×256 小图,而生产环境传的是 4K 高清图——这就是典型的缺乏基准测试导致的翻车现场。基准测试不仅能提前暴露这类问题,还能帮我们:

- 量化模型在不同硬件上的表现
- 识别性能瓶颈(是计算密集型还是 IO 卡脖子?)
- 为部署方案选择提供数据支撑(需要多少台 GPU 服务器?)
工具选型:五大框架横评
刚入门时被各种测试工具晃花了眼,这里分享我的对比清单:
| 工具名称 | 适用场景 | 学习曲线 | 特色功能 |
|---|---|---|---|
| TensorFlow Benchmark | TensorFlow 生态专属 | 低 | 内置分布式测试支持 |
| MLPerf | 跨框架硬核比拼 | 高 | 行业标准指标 |
| PyTorch Lightning | 快速搭建测试管道 | 中 | 与训练代码无缝集成 |
| Locust | 模拟高并发请求 | 低 | HTTP 接口压测专家 |
| Apache Bench | 极简 HTTP 测试 | 极低 | 快速验证 API 基础性能 |
个人建议:从 PyTorch Lightning 开始,既能复用训练代码,又方便后续扩展。
手把手搭建测试框架
下面是用 PyTorch Lightning 实现的测试骨架,重点看 @profile 装饰器的妙用:
import torch
from functools import wraps
from pytorch_lightning import LightningModule
# 内存监控装饰器
def profile(func):
@wraps(func)
def wrapper(*args, **kwargs):
torch.cuda.reset_peak_memory_stats() # 重置 CUDA 统计
start_mem = torch.cuda.memory_allocated()
start_time = time.perf_counter()
result = func(*args, **kwargs)
latency_ms = (time.perf_counter() - start_time) * 1000
end_mem = torch.cuda.max_memory_allocated()
print(f"{func.__name__}耗时:{latency_ms:.2f}ms, 内存占用:{(end_mem-start_mem)/1024**2:.2f}MB")
return result
return wrapper
class BenchmarkModel(LightningModule):
def __init__(self, model):
super().__init__()
self.model = model
@profile
def predict_step(self, batch, batch_idx):
with torch.no_grad():
return self.model(batch[0])
关键指标计算逻辑
-
P99 延迟:把所有请求的延迟排序,取第 99 百分位的值。这个比平均延迟更能反映长尾问题:
import numpy as np latencies = [120, 85, 93, ..., 210] # 单位 ms p99 = np.percentile(latencies, 99) -
吞吐量:单位时间处理的样本数。注意要预热 GPU 后再计算:
# 先跑 100 次空转消除冷启动影响 for _ in range(100): model(torch.rand(1,3,224,224)) # 正式测试 start = time.time() for _ in range(1000): model(torch.rand(32,3,224,224)) # batch_size=32 throughput = 1000*32/(time.time()-start)
三大避坑指南
数据分布的陷阱
测试时用了 ImageNet 的猫咪图片,实际用户上传的却是医疗 X 光片?建议:
- 保存生产环境请求的样本统计(均值 / 方差)
- 测试时用 KL 散度验证数据分布差异
CUDA 冷启动玄学
第一次推理总是特别慢,因为要初始化 CUDA 上下文。解决方法:
- 测试前先跑几次空推理
- 使用
torch.backends.cudnn.benchmark = True启用自动优化
Batch Size 的双刃剑
增大 batch 能提升吞吐量,但会暴增显存占用。建议绘制曲线找到拐点:
batch_sizes = [1, 4, 8, 16, 32, 64]
for bs in batch_sizes:
inputs = torch.rand(bs, 3, 224, 224).cuda()
# 测试显存和耗时...
可视化测试结果
用 Matplotlib 生成专业报告:
import matplotlib.pyplot as plt
plt.figure(figsize=(12,4))
plt.subplot(121)
plt.plot(batch_sizes, throughputs, 'bo-')
plt.xlabel('Batch Size')
plt.ylabel('Throughput (img/s)')
plt.subplot(122)
plt.plot(batch_sizes, memory_usages, 'r^-')
plt.xlabel('Batch Size')
plt.ylabel('GPU Memory (MB)')
plt.savefig('benchmark.png')
留给读者的思考题
当我们需要把模型部署到树莓派这类边缘设备时:
– 该如何设计轻量化的测试方案?
– 是否需要引入温度监控等特殊指标?
– 如何模拟真实的网络波动环境?
欢迎在评论区分享你的实战经验!
正文完
