Haswell架构增加了AVX2和FMA指令集,其中FMA指令集就是256位的融合乘加指令,根据架构图中所示,port0和port1端口各有一个FMA单元,所以Haswell架构的理论峰值就等于2port * 8 * 2(mul+add) * 频率 * 核心数。例如i7系列的最高版本i7 4790k,四核心,关闭睿频固定4GHz频率,那么浮点峰值就是2 * 8 * 2 * 4 * 4 = 512 GFLOPS,每个核心的峰值就是128 GFLOPS。
如果要实测Haswell的理论峰值,与SNB大部分思路是相同的。除了用到不同的指令以外,与SNB还有如下一些区别:fma指令的某个参数寄存器,既做输入也做输出,这样前后两个相邻循环间的同一条fma,就形成了RAW型寄存器依赖。所以如果每个循环还要求一个周期执行,并发射两条fma指令,相邻循环间肯定就会有数据依赖发生,要等待前一个循环的两条fma执行完毕才能进行第二次循环的两条fma,这就会导致流水线停顿,浪费时钟周期。假设fma指令的执行周期是k,那么解决办法就是一次循环内安排2k个数据无依赖的fma指令。经过试验,我们发现放10条fma指令到一个周期,浮点吞吐刚好达到最大值:
.loop:
vfmadd132ps %ymm0, %ymm0, %ymm0
vfmadd132ps %ymm1, %ymm1, %ymm1
vfmadd132ps %ymm2, %ymm2, %ymm2
vfmadd132ps %ymm3, %ymm3, %ymm3
vfmadd132ps %ymm4, %ymm4, %ymm4
vfmadd132ps %ymm5, %ymm5, %ymm5
vfmadd132ps %ymm6, %ymm6, %ymm6
vfmadd132ps %ymm7, %ymm7, %ymm7
vfmadd132ps %ymm8, %ymm8, %ymm8
vfmadd132ps %ymm9, %ymm9, %ymm9
sub $0x1, %rax
jne .loop
所以haswell架构下fma指令的执行延迟就是5个周期。感兴趣的同学可以试试改变循环内fma指令数量,看看测出来的GFLOPS有何变化。
我在自己的i7 4790k上测试了这个例子,结果如下: