2. CPU与GPU架构差异对基准测试的影响

做CPU与GPU的性能基准测试,最容易犯的错误是“用同一套方法测两种完全不同的机器”。CPU和GPU虽然都执行指令、都有缓存和内存,但它们的微架构目标截然不同:CPU追求单线程低延迟与通用性,GPU追求海量线程下的高吞吐。这种差异直接决定了基准测试该测什么、怎么测、看哪个指标。本节从缓存层次、流水线、线程模型和内存带宽四个维度展开对比,并落到基准测试的设计原则上。

缓存层次:延迟敏感 vs 带宽敏感

CPU的缓存层次是“小而快、层层设防”:L1通常为32~64KB、访问延迟约4~5个周期;L2为256KB~2MB、延迟约12~20周期;L3为数十MB、延迟约40~60周期;再往下是容量大但延迟上百周期的DRAM。CPU通过乱序执行、预取和深层缓存把“平均访存延迟”压到最低,因此CPU基准测试非常在意缓存命中率和工作集大小——同一段代码,工作集从L2的512KB扩大到L3的32MB,性能可能下降数倍。

GPU则相反:每个SM的共享内存/L1只有几十到两百多KB,但通过成千上万个线程的并发切换来“掩盖”访存延迟。GPU不追求单次访问快,而追求在延迟期间有足够多的warps可以调度。因此GPU基准测试更关注访存是否合并(coalesced)、占用率(occupancy)是否足以隐藏延迟,而不是单纯看缓存命中率。一个在CPU上因缓存未命中而变慢的访问模式,在GPU上可能因为合并访问而表现良好;反之,一个随机指针追逐(pointer chasing)在CPU上尚可靠缓存缓解,在GPU上却会因无法合并而急剧恶化。

流水线与线程模型:ILP/TLP 的不同侧重

CPU流水线深(十几到二十级),配合分支预测、乱序执行和寄存器重命名,从单线程中挖掘指令级并行(ILP)。因此CPU基准测试中,分支密集、依赖链长的代码(如解释器、压缩、加解密)能真实反映其能力;而纯顺序、无分支的循环反而测不出CPU的优势。

GPU采用SIMT(单指令多线程)模型:32个线程组成一个warp,共享一条指令流,靠线程级并行(TLP)填满流水线。分支在warp内发散时会被串行化执行,这是GPU的固有代价。因此GPU基准测试必须考虑warp内分支发散程度:如果测试负载中大量线程走不同分支,测得的结果会显著低于理论峰值,而这恰恰是真实负载的常见形态,不能简单归为“测试不准”。

线程模型差异还影响测试的“规模设定”。CPU测试通常固定线程数等于物理核数(或超线程数),关注单核与多核的扩展比;GPU测试则要设定grid/block尺寸,使block大小为warp的整数倍(如256),并保证足够多的block填满所有SM。block太小会导致占用率不足,太大则可能因寄存器压力降低并发度——这些参数本身就是GPU基准测试的一部分。

内存带宽:容量与带宽的权衡

CPU内存子系统强调低延迟和缓存一致性,单路带宽通常在几十到上百GB/s量级;GPU则配备HBM/GDDR,带宽可达数百GB/s到数TB/s,但单次访问延迟高。这决定了:算术强度低、数据复用少的负载(如大规模向量加法、流式拷贝)在GPU上收益巨大;而数据依赖强、随机访问多的负载在CPU上更稳。基准测试若只报“峰值带宽利用率”,会掩盖访问模式的影响,应同时报告有效带宽与理论带宽之比。

CPU 与 GPU 微架构差异 → 基准测试设计取向 多核 CPU:低延迟 · 通用 缓存层次(小容量、低延迟) L1 32–64KB L2 256KB–2MB L3 数十MB 延迟约 4 → 60 周期,逐级放大 关注:命中率、工作集大小 深流水线 + 乱序执行 取指 译码 乱序 执行 挖掘 ILP,分支预测 + 预取 关注:单线程 IPC、分支密集负载 内存:低延迟、带宽中等 单路带宽约几十~上百 GB/s 缓存一致性、随机访问友好 关注:延迟、依赖链、指针追逐 SIMT GPU:高吞吐 · 并行 共享内存 / L1(小、按 SM 划分) SM 共享内存 L1 / 纹理缓存 靠海量 warp 切换掩盖延迟 关注:合并访问、占用率 SIMT:warp 内 32 线程同指令 T0 T1 T2 T3 … T31 分支发散 → warp 内串行化 关注:TLP、block 尺寸、发散度 显存:高带宽、高延迟 HBM/GDDR,数百 GB/s ~ 数 TB/s 合并访问决定有效带宽 关注:有效带宽 / 理论带宽

差异如何决定基准测试的设计原则

把上述差异落到测试设计上,可以归纳为三条原则。第一,测试负载必须与目标架构的并行形态匹配。测CPU多核扩展性时,应让每个线程处理独立数据块并固定总工作量,观察加速比随线程数的变化;测GPU时,应让grid规模远大于SM数量,并报告不同block尺寸下的吞吐,而不是只报一个最优值。第二,指标选择要区分延迟型与吞吐型。CPU侧优先看单线程IPC、每周期指令数、缓存未命中率(可用perf stat采集);GPU侧优先看有效带宽、占用率、warp发散比例和SM利用率(可用Nsight Compute采集)。第三,控制变量要显式声明。例如CPU测试需锁定频率、关闭超线程或明确开启,GPU测试需固定时钟、声明是否开启ECC,否则跨平台对比没有意义。

一个常见的误区是拿CPU的“峰值FLOPS”与GPU的“峰值FLOPS”直接比较。CPU峰值通常指所有核在AVX满载下的理论值,实际负载很难达到;GPU峰值则依赖高占用率和无分支发散。基准测试报告应同时给出“理论峰值”和“实测达到比例”,并说明负载特征,否则数字之间不可比。

一个可操作的对比测试示例

假设要对比一颗8核CPU与一块中端GPU在“向量缩放”负载上的表现(以下参数为教学示例,非实测)。CPU侧用OpenMP,数组长度设为L3容量的2倍以制造缓存压力,线程数取1、2、4、8,记录每档的耗时与加速比;GPU侧用CUDA,block取128/256/512三档,grid覆盖全部数据,记录有效带宽并与显存理论带宽相除。判读时:若CPU加速比在4线程后明显放缓,说明受内存带宽或共享资源限制;若GPU在block=512时带宽反而下降,通常是寄存器压力导致占用率降低。这样的测试才真正把“架构差异”变成了可观察、可解释的数据。

归根结底,CPU与GPU的基准测试不是同一把尺子量两种东西,而是各自用适配其微架构的尺子。理解缓存层次、流水线、线程模型和内存带宽的差异,才能设计出既公平又有解释力的测试,让指标真正回答“这台机器适合跑什么”。