我的程序中有这个块:
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;
这真的更快吗?
答案 0 :(得分:9)
修改强>:
刚编译好您的示例,使用GCC / LLVM,进行了不同的优化,并查看了ARM6和ARM7程序集,以下是我的结论:
以下是使用您提到的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。
注意它可能会改变:
我现在有点懒惰来反汇编代码,但也许我稍后会编辑这个答案。
所以我认为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)
为了便于阅读,您不是编译器