if else vs math映射小序列

时间:2016-12-21 08:09:18

标签: python c performance if-statement mapping

我最近不得不将整数的符号转换为-1或1

我想知道,通过if else语句或进行计算是否更快?

#if else#
s == -1 ? -1 : 1

#calculation#
ceil((s + 1) / 2) * 2 - 1

我知道这是一个非常简单的例子,但有时你需要绘制更大的间隔,直观地说,似乎数学会更快,以免较小的数学。

此外,相对速度如何受所用语言的影响(例如Python与C)。

4 个答案:

答案 0 :(得分:4)

?运算符会稍微快一点,因为它涉及的指令数量较少,而我们的日子处理器通常足够聪明,不会破坏管道,虽然它应该是这样的:

int r = (s < 0) ? -1 : 1;

括号内容清晰明了。

如果s只能是-1,0或1,我建议:

int v[] = { -1, 1, 1 };
int r = v[s+1];

这永远不会破坏CPU管道。

答案 1 :(得分:1)

现代编译器并非愚蠢。例如,他们不会为有条件的动作做出愚蠢的不必要的跳跃。 (但这并不是说他们很聪明。)鉴于return x == -1 ? -1 : 1;,Clang和GCC分别产生

sgn:                                    # @sgn
    cmp     edi, -1
    mov     eax, 1
    cmove   eax, edi
    ret

sgn:
    xor     eax, eax
    cmp     edi, -1
    setne   al
    lea     eax, [rax-1+rax]
    ret

这些非常好,但我希望转变+ or更快。 return (2 * -(x < 0)) + 1;编译为

sgn:                                    # @sgn
    sar     edi, 30
    or      edi, 1
    mov     eax, edi
    ret

sgn:
    mov     eax, edi
    sar     eax, 31
    or      eax, 1
    ret

分别。这些都非常快。

在CPython上也是如此,因为那是一名翻译。

答案 2 :(得分:0)

如果性能确实非常重要,我认为很难打败通过

  1. 减1。
  2. 提取符号位。
  3. 在C语言中,你可以使用几个内联汇编语句来解决这个问题,具体取决于你的平台。

    这可能会超过等效的三元条件(实际为s <= 0 ? -1 : 1),因为不正确的分支分支预测将导致CPU转储管道。

    通过这样的微优化,您需要使用分析来回答它,建立一个适当的测试框架并将性能测量到适当的统计显着性水平。

答案 3 :(得分:0)

在Python中,布尔运算符比数学运算快5倍:

%timeit (math.ceil((s + 1) / 2) * 2 - 1)
# 1000000 loops, best of 3: 381 ns per loop

%timeit (-1 if s < 0 else 1)
#10000000 loops, best of 3: 70.1 ns per loop

在Python中,您还可以使用直接字典查找,这几乎与布尔值一样好:

d = {-1:-1, 0:-1, 1:1}
%timeit d[s]
#10000000 loops, best of 3: 73.8 ns per loop