python - Python 会自动用 << 1 替换 * 2 吗?

标签 python python-3.x cpython python-internals

我看到一些建议(请参阅 Is multiplication and division using shift operators in C actually faster?),您不应手动将乘法替换为移位运算符,因为编译器必须自动执行此操作,而移位运算符会降低可读性。我写了一个简单的测试来检查这个:

import numpy as np
import time

array1 = np.random.randint(size=10 ** 6, low=0, high=10 ** 5)
array2 = np.zeros((10 ** 6,), dtype=np.int)

total = 0.0
for i in range(100):
    start = time.clock()
    for j in range(len(array2)):
        array2[j] = array1[j] * 2
    total += time.clock() - start
print("*2 time = " + str(round(total / 10, 5)) + " ms")


total = 0.0
for i in range(100):
    start = time.clock()
    for j in range(len(array2)):
        array2[j] = array1[j] << 1
    total += time.clock() - start
print("<< 1 time = " + str(round(total / 10, 5)) + " ms")


total = 0.0
for i in range(100):
    start = time.clock()
    for j in range(len(array2)):
        array2[j] = array1[j] // 2
    total += time.clock() - start
print("//2 time = " + str(round(total / 10, 5)) + " ms")


total = 0.0
for i in range(100):
    start = time.clock()
    for j in range(len(array2)):
        array2[j] = array1[j] >> 1
    total += time.clock() - start
print(">> 1 time = " + str(round(total / 10, 5)) + " ms")

我使用了等效操作(* 2 等效于 << 1// 2 等效于 >> 1),结果如下:

*2 time = 5.15086 ms
<< 1 time = 4.76214 ms
//2 time = 5.17429 ms
>> 1 time = 4.79294 ms

怎么了?我的测试方法错了吗?时间测量有误吗?还是 Python 不执行此类优化(如果是,我应该害怕那个)?我在 Win 8.1 x64 上使用了 cPython 3.4.2 x64。

最佳答案

这种优化不会发生在字节码级别:

>>> import dis
>>> dis.dis(lambda x: x*2)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (2)
              6 BINARY_MULTIPLY
              7 RETURN_VALUE
>>> dis.dis(lambda x: x<<1)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (1)
              6 BINARY_LSHIFT
              7 RETURN_VALUE

dis模块允许你向你展示当你的代码被执行时“内部”Python 发生了什么,或者更准确地说,到底执行了什么。输出显示 *运算符映射到 BINARY_MULTIPLY<<运算符映射到 BINARY_LSHIFT .这两个字节码操作是用C语言实现的。

关于python - Python 会自动用 << 1 替换 * 2 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30779463/

相关文章:

python - 使用 for 循环分配列表项会导致无限循环

python-2.7 - 找不到 py_module_initializer!在 Rust 中构建 Python 模块时

python - 调试 CPython 操作码堆栈

python - 使用线程和队列时如何处理异常?

python - 是否以root身份启动supervisord?

python - 尽管安装了 GEOS,但获取 "django.core.exceptions.ImproperlyConfigured: GEOS is required and has not been detected."

python - 澄清行为 : collections. defaultdict 与 dict.setdefault

python - 将嵌套列表值附加到新列表中

python - 如何根据上下文更改 Blender 2.63 中的运算符(operator)标签?

python - 为什么 refs 在 Python 中每个新对象都会增加 2?