ona*_*000 6 c optimization ada branch-prediction
我有一个简单的问题,假设我有以下代码,并且它以类似的方式重复10次,例如.
if blah then
number = number + 2^n
end if
Run Code Online (Sandbox Code Playgroud)
评估会更快吗?
number = number + blah*2^n?
Run Code Online (Sandbox Code Playgroud)
这也带来了问题,你可以将一个布尔值乘以一个整数(虽然我不确定从2 ^ n返回的类型,是整数还是unsigned..etc)?(我在Ada工作,但是我们可以尝试概括一下吗?)
编辑:对不起我应该澄清我正在考虑2的力量n,并且我把c放在那里因为我对将来自己的学习感兴趣如果我遇到c中的这个问题并且我认为还有更多的c那些程序员在这些板上然后Ada(我假设你知道这意味着什么),但是我目前的问题是Ada语言,但问题应该是相当语言独立的(我希望).
Jen*_*edt 10
这个问题没有一般的答案,这在很大程度上取决于你的编译器和CPU.现代CPU有条件移动指令,所以一切皆有可能.
这里要知道的唯一方法是检查生成的汇编程序(通常-S作为编译器选项)并进行测量.
在阿达...
原始配方:
if Blah then
Number := Number + (2 ** N);
end if;
Run Code Online (Sandbox Code Playgroud)
另一种通用公式,假设Blah的类型为Boolean,Number和N属于合适的类型:
Number := Number + (Boolean'pos(Blah) * (2 ** N));
Run Code Online (Sandbox Code Playgroud)
(对于N和Number用户定义的整数或浮点类型,合适的定义和类型转换的可能需要,这里的关键点是Boolean'pos()构建体,其阿达保证会给你预定义的布尔类型0或1).
至于这是否更快,我同意@Cthutu:
我会保留条件.此时您不应该担心低级优化细节.编写最能描述算法的代码并信任编译器.
如果我们在谈论C并且blah不在你的控制之内,那么就这样做:
if(blah) number += (1<<n);
在C中确实没有布尔值,并且不需要,false为零且true不为零,因此您不能假设零不是1,这是您的解决方案所需要的,也不能假设任何特定的设置为blah,例如:
number += (blah&1)<<n;
不一定有效,因为0x2或0x4或任何非零,清零位被认为是真的.通常你会发现0xFFF ... FFFF(减1或全部)用作true,但你不能依赖典型的.
现在,如果你完全控制了blah中的值,并将其严格保持为0表示false,1表示true,那么你可以做你所问的问题:
number += blah<<n;
并避免分支,额外缓存行填充等的可能性.
回到通用案例,采用这种通用解决方案:
unsigned int fun ( int blah, unsigned int n, unsigned int number )
{
if(blah) number += (1<<n);
return(number);
}
并编译两个最受欢迎/使用的平台:
testl %edi, %edi
movl %edx, %eax
je .L2
movl $1, %edx
movl %esi, %ecx
sall %cl, %edx
addl %edx, %eax
.L2:
以上使用条件分支.
下面的一个使用条件执行,没有分支,没有管道刷新,是确定性的.
cmp r0,#0 movne r3,#1 addne r2,r2,r3,asl r1 mov r0,r2 bx lr
可以通过在函数调用中重新安排参数来保存mov r0,r2指令,但这是学术性的,你通常不会在这上面烧掉一个函数调用.
编辑:
建议:
unsigned int fun ( int blah, unsigned int n, unsigned int number )
{
number += ((blah!=0)&1)<<n;
return(number);
}
subs r0, r0, #0 movne r0, #1 add r0, r2, r0, asl r1 bx lr
当然更便宜,而且代码看起来不错,但我不会假设blah!= 0的结果,即零或编译器定义为true的任何内容总是设置为lsbit.它不必为编译器设置该位以生成工作代码.也许标准规定了真实的具体价值.通过重新排列函数参数,if(blah)数+ = ...也将导致三个单时钟指令而没有假设.
EDIT2:
看看我理解为C99标准:
==(等于)和!=(不等于)运算符类似于关系运算符,除了它们的优先级较低.如果指定的关系为真,则每个运算符产生1,如果为假,则产生0.
这解释了为什么上面的编辑工作以及为什么你得到movne r0,#1而不是其他一些随机数.
海报在询问关于C的问题,但也注意到ADA是当前的语言,从语言独立的角度来看,你不应该假设"功能",如上面的C功能,并使用if(blah)数字=数字+(1 << N).但这是用C标签询问的,所以C的一般(处理器无关)最快的结果是,我认为,数字+ =(blah!= 0)<< n; 所以史蒂文赖特的评论是正确的,他应该为此获得赞誉.
海报假设基本上也是正确的,如果你可以把它变成0或1形式,那么在数学中使用它会更快,因为没有分支.如果没有它比分支更昂贵就可以进入这种形式.
| 归档时间: |
|
| 查看次数: |
4636 次 |
| 最近记录: |