在iPhone中,三元操作比“if / else”更好

时间:2011-05-27 17:15:20

标签: iphone ios arm

我的程序中有这个块:

if (x > 0) {
    a = 1;
    b = 4;
} else {
    a = 2;
    b = 3;
}

这可以用这样的三元运算编写:

a = (x > 0) ? 1 : 2;
b = (x > 0) ? 4 : 3;

结果是等价的,但它是我应用程序真正关键部分的一部分,每秒运行数千次。我想挤一些微秒,因为这种方法会增长一点。

我的问题:在ARM级别,哪一个更快?我相信第一个创建分支指令。但三元运作怎么样?它也成为iPhone上的一个分支吗?或iPhone的ARM有一个邪恶的操作码来完成这项工作?

顺便说一句,我也看到了这样一种邪恶的技巧:

a = (x > 0) * 1 + (x <= 0) * 2;

这真的更快吗?

7 个答案:

答案 0 :(得分:9)

修改

刚编译好您的示例,使用GCC / LLVM,进行了不同的优化,并查看了ARM6和ARM7程序集,以下是我的结论:

  • ARM-ASM因GCC / LLVM和目标架构而异。
  • 但是,使用最高优化级别时它为if和ternary 生成完全相同的汇编代码,无论编译器/ arch是什么。 (是的,比较了几对;)

以下是使用您提到的IT指令的LLVM / ARM7最简洁的结果,如果三元:

MOVS    R1, #2
CMP     R0, #0
IT GT
MOVGT   R1, #1
MOV.W   R2, #3
IT GT
MOVGT   R2, #4

<强> ENDOFEDIT

刚刚对该主题进行了一些搜索,即使some people thinks ternary is less optimized结果最多且更相关,也说it produce the same assembly code

注意它可能会改变:

  1. 编译器GCC,LLVM ......
  2. 优化级别
  3. 我现在有点懒惰来反汇编代码,但也许我稍后会编辑这个答案。

    所以我认为djna是正确的,设置为2 * (x>0),如果不进行优化会非常令人惊讶,这是相同的。

    之后,ternary or not,这是一个品味问题。 我更喜欢在代码中有意义的三元数,而是可读的

    关于第二个例子,它是一个技巧,它使用了这个事实:= = 1 / false == 0 ... 有趣,但我不想保留该代码。

答案 1 :(得分:3)

没有

代码高尔夫没有赢家。

可读性获胜。

因此,在这种情况下,使用传统条件块的第一个示例大约7099092034902次更容易阅读。任何熟悉编程的人都能够理解正在发生的事情。

在后一个例子中...上帝,那是什么!

答案 2 :(得分:3)

智能编译器可以为任一代码生成相同的输出。

非智能编译器会导致(X> 0)在三元运算符的情况下被评估两次,因此会更慢!

答案 3 :(得分:1)

花了数年时间优化软件,我愿意打赌你上面发布的小块并不是你的问题。我认为我们需要看到整个方法以及一些分析结果(当涉及到优化,测量是一切时)以便更好地处理它。

要回答你自己的问题 - 采取每个选项并对其进行分析,例如1000万次调用(只有几千个不会告诉你关于上面片段的任何内容)。这将告诉你哪个最适合速度,没有必要再次猜测。

答案 4 :(得分:0)

  

我的问题:在ARM级别,哪一个更快?

为什么不编写一个简单的测试程序来测量每个块的100000次调用的执行速度?

答案 5 :(得分:0)

没有区别,gcc会将一个简单的if和一个三元运算符编译成相同的代码。如果您真的想在ARM asm级别优化代码,那么可以通过使用条件ARM asm代码来避免分支,从而获得显着的加速。但是,为了做到这一点,您需要分析您的代码并找出它真正需要的位置。然后,您需要仅为代码中的热点手动编写ARM asm代码。基本上,如果您不需要极大的性能改进,那么只需使用编译器提供的功能,因为编译器在大多数情况下都做得很好。

答案 6 :(得分:-1)

为了便于阅读,您不是编译器