为什么按位运算符比乘法/除法/模运算慢?

时间:2019-01-04 22:36:50

标签: python optimization bitwise-operators micro-optimization

众所周知,乘数,整数除法和以2的幂进行模运算可以更有效地重写为按位运算:

>>> x = randint(50000, 100000)
>>> x << 2 == x * 4
True
>>> x >> 2 == x // 4
True
>>> x & 3 == x % 4
True

在C / C ++和Java等编译语言中,测试表明,按位运算通常比算术运算更快。 (请参见herehere)。但是,当我在Python中测试它们时,却得到相反的结果:

In [1]: from random import randint
   ...: nums = [randint(0, 1000000) for _ in range(100000)]

In [2]: %timeit [i * 8 for i in nums]
7.73 ms ± 397 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [3]: %timeit [i << 3 for i in nums]
8.22 ms ± 368 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [4]: %timeit [i // 8 for i in nums]
7.05 ms ± 393 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [5]: %timeit [i >> 3 for i in nums]
7.55 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [6]: %timeit [i % 8 for i in nums]
5.96 ms ± 503 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [7]: %timeit [i & 7 for i in nums]
8.29 ms ± 816 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

如您所见,按位运算比其算术运算要慢,尤其是对于模运算。我对另一组数字重复了此测试,并得到了相同的结果。是否有一个原因?如果重要的话,这些测试是在CPython 3.6.7中进行的。

3 个答案:

答案 0 :(得分:10)

*%/都具有单“四肢”整数的快速路径。 <<>>&没有。他们正在通过通用的任意精度代码路径。

答案 1 :(得分:1)

我测试大量数字,按位运算符更快。

python -m timeit '[i for i in range(10**64, 10**64+1000) if i & 0b10==0]'
1000 loops, best of 3: 238 usec per loop

python -m timeit '[i for i in range(10**64, 10**64+1000) if i % 2==0]'
1000 loops, best of 3: 303 usec per loop

答案 2 :(得分:-1)

Python是一种解释型语言,因此,在使您与机器代码分离的复杂指令中,您可能会在任何地方失去速度。

如果这种速度差异对您很重要,则您可能应该使用NumPy,它将使您能够以更接近于已编译代码的级别对数​​字进行批量处理。