您的位置:首页 > 编程语言

连载:编写高效代码(11) 尽量减少分支

2011-12-09 22:39 471 查看
我们在介绍处理器时,已经知道了,现在的处理器都是流水线结构,if和switch等语句会带来跳转,而跳转会打乱流水线的正常执行,影响程序的执行效率。
下面这段代码,把奇数赋一个值,把偶数赋一个值,可以用这种方式实现:

for(i=0; i<100; i++)

{

if(i%2 == 0)

{

a[i] = x;

}

else

{

a[i] = y;

}

}


如果改成如下这种形式就更好了:

for(i=0; i<100; i+=2)

{

a[i] = x;

a[i+1] = y;

}


将最可能进入的分支放在 if中,而不是else中

Intel处理器有分支预测单元,第一次进入一个分支时,由于没有历史信息可供参考,是否跳转取决于Static Predictor(静态预测器)的预测策略,通常Static Predictor的策略是:向下跳转预测为不跳转,向上跳转预测为跳转。根据这个特性,我们在写if else语句时,也要注意。且看下面这段代码是否合适?

int a = -5;

int b = 0;

if (a > 0)

{

b = 1;

}

else

{

b = 2;

}


我们来看看汇编语言:

4:        int a = -5;

00401028   mov         dword ptr [ebp-4],0FFFFFFFBh

5:        int b = 0;

0040102F   mov         dword ptr [ebp-8],0

6:        if (a > 0)

00401036   cmp         dword ptr [ebp-4],0

0040103A   jle         main+35h (00401045)

7:        {

8:            b = 1;

0040103C   mov         dword ptr [ebp-8],1

9:        }

10:       else

00401043   jmp         main+3Ch (0040104c)

11:       {

12:           b = 2;

00401045   mov         dword ptr [ebp-8],2

13:       }
读者没必要管这么一大串汇编语言是什么意思,只需要知道jle是个条件跳转指令就可以了,它跳到地址00401045处,是向下跳,根据Static Predictor的策略,它被预测为不跳转,处理器会从0040103C地址处开始取下一条指令。再看看实际的执行情况,a<0,执行else这个分支,于是处理器发现取错了地址,又要从头来过,白白浪费了大量时间。可见,执行概率高的分支,应该放在if分支中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: