我可以替换我的if语句以节省运行时间吗?

时间:2019-01-18 13:12:05

标签: c++ if-statement

我目前正在尝试提高程序速度。

我想知道是否将有助于替换所有类型的if语句:

bool a=1;
int b=0;
if(a){b++;}

与此:

bool a=1;
int b=0;

b+=a;

我不确定从bool到int的转换在时间上是否会成为问题。

2 个答案:

答案 0 :(得分:3)

编程时的一个经验法则是不进行微优化。

另一条规则是编写清晰的代码。

但是在这种情况下,适用另一条规则。如果要编写优化的代码,请避免使用任何可能导致分支的代码,因为由于分支预测失败,可能导致不必要的cpu​​管道转储。

还请记住,汇编器中没有boolint类型:只是寄存器,因此您可能会发现所有转换都会被优化。因此

b += a;

为我赢;也更清楚。

答案 1 :(得分:2)

允许编译器假定bool的基础值没有被弄乱,因此优化编译器 可以避免分支。

如果我们在at the generated code上进行人工测试

int with_if_bool(bool a, int b) {
    if(a){b++;}
    return b;
}

int with_if_char(unsigned char a, int b) {
    if(a){b++;}
    return b;
}

int without_if(bool a, int b) {
    b += a;
    return b;
}

clang将利用这一事实并生成与a版本的bbool相加的完全相同的无分支代码,而在{{1}中使用零进行实际比较} case(尽管它仍然是无分支的代码):

unsigned char

gcc会像对待with_if_bool(bool, int): # @with_if_bool(bool, int) lea eax, [rdi + rsi] ret with_if_char(unsigned char, int): # @with_if_char(unsigned char, int) cmp dil, 1 sbb esi, -1 mov eax, esi ret without_if(bool, int): # @without_if(bool, int) lea eax, [rdi + rsi] ret 一样对待bool,而不利用其属性,生成与clang的unsigned char情况类似的代码。

unsigned char

最后,Visual C ++会像gcc一样平等对待with_if_bool(bool, int): mov eax, esi cmp dil, 1 sbb eax, -1 ret with_if_char(unsigned char, int): mov eax, esi cmp dil, 1 sbb eax, -1 ret without_if(bool, int): movzx edi, dil lea eax, [rdi+rsi] ret bool版本,尽管具有更幼稚的代码源(它使用条件移动而不是使用标志寄存器执行算术,传统上,IIRC的效率较低(对于当前的机器不知道)。

unsigned char

在所有情况下,都不会生成分支;唯一的不同是,在大多数编译器上,生成了一些更复杂的代码,这些代码依赖于a$ = 8 b$ = 16 int with_if_bool(bool,int) PROC ; with_if_bool, COMDAT test cl, cl lea eax, DWORD PTR [rdx+1] cmove eax, edx ret 0 int with_if_bool(bool,int) ENDP ; with_if_bool a$ = 8 b$ = 16 int with_if_char(unsigned char,int) PROC ; with_if_char, COMDAT test cl, cl lea eax, DWORD PTR [rdx+1] cmove eax, edx ret 0 int with_if_char(unsigned char,int) ENDP ; with_if_char a$ = 8 b$ = 16 int without_if(bool,int) PROC ; without_if, COMDAT movzx eax, cl add eax, edx ret 0 int without_if(bool,int) ENDP ; without_if cmp,从而创建了更长的依赖链。

话虽如此,只有当您实际在探查器下运行代码,并且结果指向该特定代码(或涉及该代码的紧密循环)时,我才会担心这种微优化。通常,您应该编写明智的,语义正确的代码,并专注于使用正确的算法/数据结构。稍后会进行微优化。


  

在我的程序中,这是行不通的,因为a实际上是类型为test

的操作

这对于优化器来说应该更好,因为它甚至对b+=(a==c)的来源没有任何疑问-它可以直接从标志寄存器中进行确定。 As you can see,这里的gcc在两种情况下产生的代码非常相似,叮当声完全相同,而VC ++照例在bool情况下产生的条件性代码(cmov)更加类似