如果Thens比乘法和赋值更快吗?

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作为编译器选项)并进行测量.


Mar*_*c C 5

在阿达...

原始配方:

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)

(对于NNumber用户定义的整数或浮点类型,合适的定义和类型转换的可能需要,这里的关键点是Boolean'pos()构建体,其阿达保证会给你预定义的布尔类型0或1).

至于这是否更快,我同意@Cthutu:

我会保留条件.此时您不应该担心低级优化细节.编写最能描述算法的代码并信任编译器.


old*_*mer 5

如果我们在谈论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形式,那么在数学中使用它会更快,因为没有分支.如果没有它比分支更昂贵就可以进入这种形式.

  • 那么`数字+ =((blah!= 0)&1)<< n;`? (2认同)