理解x86 SIMD求和实现吞吐量:实测与理论不符的疑问
对Rocket Lake上向量求和流水线的分析
首先明确循环的核心工作:
- 单次循环执行4条
vaddpd指令,每条指令通过256位YMM寄存器处理4个f64(256字节/8字节=4),因此单次循环共处理16个f64。 - 循环末尾的
add rcx,16推进内存指针,cmp和jne完成循环迭代控制。
核心误解:指令依赖关系的错误判断
你提到的“每个vaddpd因依赖需每4周期执行一次”是错误的——这4条vaddpd指令彼此无数据依赖:每条指令使用独立的目标寄存器(ymm0、ymm1、ymm2、ymm3),源操作数来自内存的不同区域,不存在写后读(RAW)依赖。因此CPU无需等待前一条vaddpd完成,就能发射下一条指令。
Rocket Lake(Cypress Cove微架构)的硬件能力
Rocket Lake基于改进的Skylake微架构,其浮点与整数单元具备并行调度能力:
- 浮点加法(含
vaddpd)的吞吐量为每周期2条256位向量指令(配备2个独立的FP加法执行端口)。 - 整数指令(
add、cmp、jne)由独立的整数执行端口处理,可与浮点指令并行运行,几乎不额外占用周期。
实测吞吐量的解释
10亿个f64耗时2亿周期,计算得每周期处理5个f64:
- 单次循环处理16个
f64,对应循环次数为10亿/16=6250万次,单次循环平均耗时2亿/6250万=3.2周期。这个数值完全符合硬件并行能力:- 4条
vaddpd可在2个周期内完成(每周期发射2条)。 - 整数循环控制指令与浮点指令并行执行,几乎不增加循环耗时。
- 4条
- 每周期处理5个
f64,等价于每周期执行1.25条vaddpd指令,远低于硬件2条/周期的吞吐量上限,说明此时循环的瓶颈是内存带宽(10亿f64对应8GB数据,2亿周期在3.6GHz的11700K上约为55ms,带宽约145GB/s,接近DDR4-3200的单通道带宽上限)。
总结
你的理论推导错误源于对指令依赖关系的误判——独立寄存器的向量指令可并行发射,不受单条指令延迟的限制。实测吞吐量是硬件并行调度与内存带宽共同作用的结果,完全符合Rocket Lake的微架构特性。
内容的提问来源于stack exchange,提问作者benjamin-lieser
相关产品推荐
相关产品推荐

