分支预测与流水线
现代CPU会使用大量的流水线,并配合分支预测进行运行效率的提升。
分支预测即就是通过对程序if else
等条件分支进行预测,并提前执行相关代码。如果预测正确,显然会提升效率,如果预测失败,那么将不得不清空流水线,重新来过,此时便会影响效率。
目前市面上主流CPU的分支预测,正确率可以达到90%以上。
避免分支预测开销
编译器会进行一定的优化,主要是将条件分支语句转化为条件传送语句。
优化前:
1
2
3
4if( a > b )
return a - b ;
else
return b - a;
优化后:
1
return a > b ? a - b : b - a ;
这两种写法的区别在于,第二种写法,在编译器优化情况下,会被转化成条件传送语句comvl
,CPU可以不需要预测就继续执行下去。效率因此得到提高。
那么,作为程序员都有哪些方法去写更优雅的代码,提升效率呢?
合并条件
主要是通过优化,尽可能减少分支预测失败时对效率的影响。
优化前:
1
2
3if(case1)
if( case2 )
do();
优化后:
1
2if( case1 && case2 )
do();
优化前:
1
2if( case1 == 0 && case2 == 0 && case3 == 0 )
do();
优化后:
1
2if( ( case1 | case2 | case3 ) == 0 )
do();
提前进行分支预测
主要通过提前进行分支预测,避免在循环中大量的预测错误,导致开销。
优化前:
1
2
3
4
5for( int i = 0 ; i < n ; i++)
if( case1 )
do1();
else
do2();
优化后:
1
2
3
4
5
6
7
8if( case1 )
flag = 1 ;
if( flag )
for( int i = 0 ; i < n ; i++ )
do1();
else
for( int i = 0 ; i < n ; i++ )
do2();
跳转取消分支预测
如将if else
改写switch
(switch
使用跳转指令,直接跳转到对应分支)
将多个函数使用函数指针,直接进行调用等。
位运算取消预测
如对于if(color < 0 ) color = 0
,可改成color &=~(color >> 31 )