首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >If语句和if-else语句,哪个更快?

If语句和if-else语句,哪个更快?
EN

Stack Overflow用户
提问于 2017-04-04 16:28:49
回答 6查看 20K关注 0票数 89

前几天,我和一个朋友就这两个片段发生了争执。哪个更快?为什么?

代码语言:javascript
复制
value = 5;
if (condition) {
    value = 6;
}

和:

代码语言:javascript
复制
if (condition) {
    value = 6;
} else {
    value = 5;
}

如果value是一个矩阵呢?

注意:我知道value = condition ? 6 : 5;是存在的,我希望它会更快,但这不是一个选择。

编辑(由于问题暂时搁置,因此由员工请求):

  • 请考虑主流编译器(例如g++、clang++、vc、mingw)在优化和非优化版本中生成的x86程序集或MIPS程序集作为回答。
  • 当程序集不同时,解释为什么版本更快,以及何时(例如“更好,因为没有分支和分支有后续问题”)
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-04-04 16:40:21

TL;DR:在未经优化的代码中,没有elseif似乎效率更高,但即使启用了最基本的优化级别,代码基本上也会重写为value = condition + 5

I gave it a try并为以下代码生成了程序集:

代码语言:javascript
复制
int ifonly(bool condition, int value)
{
    value = 5;
    if (condition) {
        value = 6;
    }
    return value;
}

int ifelse(bool condition, int value)
{
    if (condition) {
        value = 6;
    } else {
        value = 5;
    }
    return value;
}

在禁用优化(-O0)的gcc 6.3上,相应的区别是:

代码语言:javascript
复制
 mov     DWORD PTR [rbp-8], 5
 cmp     BYTE PTR [rbp-4], 0
 je      .L2
 mov     DWORD PTR [rbp-8], 6
.L2:
 mov     eax, DWORD PTR [rbp-8]

用于ifonly,而ifelse

代码语言:javascript
复制
 cmp     BYTE PTR [rbp-4], 0
 je      .L5
 mov     DWORD PTR [rbp-8], 6
 jmp     .L6
.L5:
 mov     DWORD PTR [rbp-8], 5
.L6:
 mov     eax, DWORD PTR [rbp-8]

后者看起来效率稍低,因为它有一个额外的跳跃,但两者都有至少两个最多三个赋值,所以除非你真的需要压缩最后一滴性能(提示:除非你在航天飞机上工作,否则你不会这样做,即使那样你也可能不会),差异不会明显。

然而,即使使用最低优化级别(-O1),这两个函数也会减少到相同的程度:

代码语言:javascript
复制
test    dil, dil
setne   al
movzx   eax, al
add     eax, 5

它基本上等同于

代码语言:javascript
复制
return 5 + condition;

假设condition为0或1。更高的优化级别并不会真正改变输出,除非它们通过在开始时有效地将EAX寄存器清零来避免movzx

免责声明:您可能不应该自己编写5 + condition (即使标准保证将true转换为整数类型会产生1),因为阅读您的代码的人(可能包括您未来的自己)可能不会立即看出您的意图。这段代码的要点是显示编译器在这两种情况下产生的内容(实际上)是相同的。Ciprian Tomoiaga在评论中说得很好:

人类的工作是为人类编写代码,并让编译器为编写代码。< code >J233

票数 286
EN

Stack Overflow用户

发布于 2017-04-04 22:14:15

来自CompuChip的答案显示,对于int,它们都针对相同的程序集进行了优化,所以这无关紧要。

如果

是一个矩阵呢?

我将以一种更一般的方式来解释这一点,例如,如果value是一种构造和赋值都很昂贵(而移动成本很低)的类型,那该怎么办?

然后

代码语言:javascript
复制
T value = init1;
if (condition)
   value = init2;

不是最优的,因为在condition为真的情况下,您对init1执行不必要的初始化,然后执行复制分配。

代码语言:javascript
复制
T value;
if (condition)
   value = init2;
else
   value = init3;

这个比较好。但是,如果默认构造昂贵,并且如果复制构造比初始化更昂贵,则仍然是次优的。

你有一个很好的条件运算符解:

代码语言:javascript
复制
T value = condition ? init1 : init2;

或者,如果您不喜欢条件运算符,可以创建一个辅助函数,如下所示:

代码语言:javascript
复制
T create(bool condition)
{
  if (condition)
     return {init1};
  else
     return {init2};
}

T value = create(condition);

根据init1init2是什么,您还可以考虑以下内容:

代码语言:javascript
复制
auto final_init = condition ? init1 : init2;
T value = final_init;

但我必须再次强调,只有当构造和赋值对于给定类型来说非常昂贵时,这才是相关的。即便如此,只有通过对进行分析,您才能确定。

票数 44
EN

Stack Overflow用户

发布于 2017-04-04 23:05:02

在伪汇编语言中,

代码语言:javascript
复制
    li    #0, r0
    test  r1
    beq   L1
    li    #1, r0
L1:

可能快,也可能不快

代码语言:javascript
复制
    test  r1
    beq   L1
    li    #1, r0
    bra   L2
L1:
    li    #0, r0
L2:

这取决于实际CPU的复杂程度。从最简单到最花哨:

  • 对于大约1990年以后生产的任何CPU,良好的性能依赖于instruction cache中的代码拟合。因此,当有疑问时,请最小化代码大小。
  • 有一个基本的"in-order, five-stage pipeline“CPU,这仍然是你在许多微控制器中得到的基本CPU,每次分支-有条件的或无条件的-都会有一个pipeline bubble,所以最小化分支指令的数量也很重要。这也有利于第一个example.
  • Somewhat更复杂的CPUs足够奇特,可以做"out-of-order execution",但不够奇特,可以使用该概念的最著名的实现-可能会在遇到write-after-write hazards时引起管道泡沫。这有利于第二个示例,在该示例中,r0无论如何只编写一次。这些CPU通常足以在指令获取器中处理无条件的分支,因此您不仅仅是在用写后写的代价来换取分支代价。

我不知道还有没有人还在制造这种CPU。但是,使用乱序执行的“最著名的实现”的CPU可能会偷工减料地使用不太频繁使用的指令,因此您需要意识到这种情况可能会发生。一个真实的例子是false data dependencies on the destination registers in popcnt and lzcnt on Sandy Bridge CPUs.

  • At的最高端,OOO引擎将最终为两个代码片段发出完全相同的内部操作序列-这是硬件版本的“不用担心,编译器将以任何方式生成相同的机器代码”。但是,代码大小仍然很重要,现在您还应该担心条件分支的可预测性。Branch prediction故障可能会导致完整的管道刷新,这对性能是灾难性的;请参阅Why is it faster to process a sorted array than an unsorted array?以了解这会造成多大的差异。

如果分支是高度不可预测的,并且您的CPU具有条件设置或条件移动指令,则是时候使用它们了:

li #0,r0测试r1设置r0

li #0,测试li #1,r2 r0 r1 movne r2,r0

条件集版本也比任何其他替代方案更紧凑;如果该指令可用,即使分支是可预测的,实际上也可以保证它在这种情况下是正确的。条件移动版本需要额外的临时寄存器,并且总是浪费一条li指令的分派和执行资源;如果分支实际上是可预测的,分支版本可能会更快。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43202012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档