简介:本文给出CPU与GPU运行深度学习负载的可复现评测方法,涵盖测试环境固定、批量与并发设计、延迟与吞吐口径、稳定性与成本记录,并提供按训练、推理和通用业务划分的选型判定规则。读者可直接套用流程,用自有负载数据做出硬件决策。
CPU还是GPU更合适,取决于负载形态、延迟要求和长期成本,没有统一答案。矩阵运算占主导的训练和批量推理,通常能从GPU获得更高吞吐。小批量、分支多、要求低延迟的在线服务,CPU往往更省事,单次响应也更稳定。本文不给出某个型号的排名,而是提供一套方法,让团队用自己的负载得出结论。
本文测试对象限定为CPU和GPU。专用ASIC需要单独核对算子覆盖率,结论不能直接外推。
每组对比只改变一个主要变量。测试前,记录并固定以下参数:
| 项目 | 记录内容 | 示例 |
|---|---|---|
| 处理器 | 完整型号、核心数、基础频率 | 写明厂商型号与线程数 |
| GPU | 完整型号、显存容量、驱动版本 | 驱动版本需与CUDA版本匹配 |
| 系统 | 操作系统版本、内核版本 | 两端保持一致 |
| 软件栈 | CUDA版本、Python版本、框架版本 | 如PyTorch 2.x |
| CPU策略 | 调频策略、是否开启超线程、线程数 | 调频固定为performance |
| 运行环境 | 机房温度、是否独占机器 | 测试期间关闭无关进程 |
CPU端的线程数需要通过torch.set_num_threads()或环境变量显式设置,避免框架自动选择导致结果漂移。
建议使用三类负载,并在两种硬件上完全相同地执行:
批量大小取1、8、32、128、512。显存不足导致的失败点需要单独记录,因为它本身就是选型信息。并发设置包括单进程串行,以及4路、8路并发两组。数据使用固定随机种子生成,并记录形状和精度(FP32、FP16)。
下面的脚本计算延迟分位数和吞吐。GPU计时前后必须调用同步函数,否则测到的只是异步提交的时间。
import timeimport torchdef bench(model, x, device="cuda", warmup=20, iters=200):model.eval()use_cuda = device == "cuda"with torch.inference_mode():for _ in range(warmup):model(x)if use_cuda:torch.cuda.synchronize()lat_ms = []for _ in range(iters):t0 = time.perf_counter()model(x)if use_cuda:torch.cuda.synchronize()lat_ms.append((time.perf_counter() - t0) * 1000)lat_ms.sort()p50 = lat_ms[len(lat_ms) // 2]p95 = lat_ms[int(len(lat_ms) * 0.95) - 1]mean_ms = sum(lat_ms) / len(lat_ms)throughput = x.shape[0] * 1000 / mean_ms # 样本/秒return p50, p95, throughput
资源监控使用以下命令,采样间隔为1秒:
# GPU利用率、显存、功耗、温度nvidia-smi --query-gpu=utilization.gpu,memory.used,power.draw,temperature.gpu --format=csv -l 1# CPU每核利用率(Linux,需安装sysstat)mpstat -P ALL 1
稳定性测试连续运行2小时,每10分钟记录一次吞吐。故障注入包括极端输入尺寸、含NaN的输入,以及与依赖服务的断连。记录每种情况下的错误类型、恢复时间和后续吞吐。
| 指标 | 定义 | 计算方式 |
|---|---|---|
| 吞吐 | 每秒处理的样本数 | 批量 × 1000 ÷ 平均单次耗时(毫秒) |
| P50、P95延迟 | 单次请求耗时的分位数 | 排序后取对应位置的值 |
| 设备利用率 | 计算单元忙碌比例 | nvidia-smi采样平均值;CPU取用户态加内核态时间 |
| 显存峰值 | 运行期最大显存占用 | torch.cuda.max_memory_allocated() |
| 每千样本能耗 | 单位样本消耗的电能 | 功耗采样积分 ÷ 样本数 |
| 错误率 | 失败请求占总请求的比例 | 日志统计 |
延迟必须计入主机与设备之间的数据拷贝时间,因为线上服务的请求确实包含这部分开销。两端使用同一口径,结果才有可比性。
每组实验至少重复3次,取中位数并记录标准差。同一组内的波动超过10%时,先排查温度降频和后台进程,再采用结果。
| 硬件 | 负载 | 批量 | 并发 | 吞吐(样本/秒) | P95延迟(毫秒) | 利用率(%) | 显存峰值(GB) | 错误率(%) |
|---|---|---|---|---|---|---|---|---|
| CPU | ResNet-50 | 1 | 1 | 待填 | 待填 | 待填 | 待填 | 待填 |
| GPU | ResNet-50 | 1 | 1 | 待填 | 待填 | 待填 | 待填 | 待填 |
以下阈值是起始值,应结合业务的服务等级目标(SLA)校准后再使用。
总成本建议按以下项目测算:
主要风险包括:短时压测无法代表长期稳定性;小数据集不能代表生产规模;驱动或框架升级可能改变性能;云实例的资源共享会造成波动,应在不同时段多次测试。
回退方案建议保留CPU路径,通过流量比例灰度切换。当GPU请求的排队等待时间超过SLA的80%时,自动把部分流量切回CPU,并记录切换次数,作为后续容量规划的依据。
硬件选择应从负载特征出发。矩阵运算密集的训练和批量推理,通常更适合GPU。小批量、分支多、低延迟的服务,CPU往往更合适。这些结论只有在环境固定、指标口径统一、并用自有数据验证之后才成立。团队可以按本文的环境清单、测量