cpu out of order, 性能优化

这是以前研究生的时候写的一篇文章

今天看了一篇文章关于cpu乱序执行的讲解,主题思想是cpu能并行的处理指令,这里的并行不是多核并行的处理,而是在某种情况下,上下2条指令可以被一个核一起送行,还有可能在下面的指令先运行,称为乱序执行,out of order,这也带来了超标量,1个时钟周期可以运行大于1条指令。这在以前是不可想象的,在理想情况下,一个时钟最多执行1条,但是创新是*限的。
一个简单的实验
cpu out of order, 性能优化
过程为对eax执行3次加法,循环差不多4G次,差一点点,无关紧要,产生执行文件反汇编如下
cpu out of order, 性能优化
循环内部一共五条指令,4g次循环,就是20g个指令需要执行,使用time 计算运行时间10次测试值为
7.12 7.23 7.24 7.07 7.14 7.17 7.21 7.30 7.16 6.99这里是user时间,用户态时间,忽略其他函数包括main之前的函数执行时间
就是在这20g次得指令执行上花了大约7s时间,本机的配置为酷睿的2.1Ghz,7s的时间最多也只能有14G的周期,按照一般理论,执行不了20g次指令,这还是在每个指令都是单周期的理想情况下
这就是乱序执行带来的超标量性能。
对于此现象的稍微详细一点的解释可以是这样,
5条指令,每一条都是对cpu状态机的一个改变,对于上下没有依赖的指令可以一起执行
比如
cpu out of order, 性能优化
这2条可以并行运行,但是
cpu out of order, 性能优化
这2条就不可以并行运行,对于这5条指令可以理解为这样的一个过程
cpu out of order, 性能优化
每一行代表一个机器周期,对eax的三次相加,必须等到前一次运算完成以后才能进行下一次的相加,但是对于edx的减法就可以和第一次eax的加法一起运行,其实edx就是c代码的那个i,这里就是乱序的体现,因为edx的减法在后面,但是先于2个eax的加法运行,没有按照固定顺序。但是不管怎么乱序,指令执行完以后的结果需要和顺序的一样。jne 80483a8这个指令要等到对edx减法完成是才能运行,因为要根据减法运算的结果的判断。
所以这5条指令 4G次循环其实是3个周期 4G次循环为12g个周期,7s的时间2GHZ 处理器可以有14G个周期。所以加上main之前的库代码为2G个周期,就差不多7s 的运行时间。
以下是对代码的另一种实验。对eax的3次加法改成分别对eax ebx ecx的3次加法,这个看上去是差不多,都是对寄存器加法运算,但是对于现代的处理器有很大的差别。
c代码改为
cpu out of order, 性能优化
对于的a.out执行文件反汇编为
cpu out of order, 性能优化
循环还是5条指令和原来的一样,只是原来是eax3次加法变成现在的eax ebx ecx的三次加法,测试的运行时间为
4.31 4.48 4.28 4.33 4.28 4.25 4.19 4.34 4.34 4.33
这是绝对的减少,这就很奇怪,只是对寄存器不一样,按照上面的方法可以画一下cpu运算数据流向图
cpu out of order, 性能优化
因为对eax ebx ecx 3条指令没有上下依赖关系,目前intel处理器每个核有三个独立的加法器(可以测试具体有几个加法器),所以其实这3条指令是一起运行的,估计cpu数据流,一次循环其实只需要2个周期就可以了,4G次循环只需要8G个周期,对于一个2GHZ的处理器来说时间也刚好是4s差不多,和测试结果完全匹配。这就是cpu的乱序执行的能力。对于性能优化,在c的体现中,在循环中,在连续的几次运算中数据没有依赖性是重点。把运算过程的中间结果都放在同一个变量中会比较慢。
就算再增加一个加法运算把原来的3次改为4次,
cpu out of order, 性能优化
运算时间还是和上一次是一样的。
因为cpu数据流图
cpu out of order, 性能优化
在一个循环的运行周期上还是一样的,4.22 4.44 4.31 4.30 4.23 4.21 4.22 4.24 4.22 4.23

如果增加到5个的话,数据流回变成
cpu out of order, 性能优化
在2个时钟周期中三个加法器会满负载运行,这样就会影响到jne 80483a8的运算,
cpu out of order, 性能优化
其实这条指令也是需要加法器支持的,从上面可以看到这条指令的机器码是 75 f2效果是向前跳12个偏移,这是一个相对偏移跳转指令,运算过程为下一条指令地址0xbc+2=0xbe 加上0xf2
加上f2就是减14 等于0xb0,所以需要加法器计算最终的地址。但是加法器在前面已经满负荷运行,所以势必会增加每个循环的周期数。测试结果为
5.17 5.52 5.05 5.31 5.09 5.15 5.30 5.31 5.39 5.04
明显的比前面的运算时间要增加。

上一篇:分布式系统学习系列


下一篇:compass General 常用api学习[Sass和compass学习笔记]