Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python是否会自动将*2替换为<&书信电报;1._Python_Python 3.x_Cpython_Python Internals - Fatal编程技术网

Python是否会自动将*2替换为<&书信电报;1.

Python是否会自动将*2替换为<&书信电报;1.,python,python-3.x,cpython,python-internals,Python,Python 3.x,Cpython,Python Internals,我看到一些建议(例如),你不应该用移位运算符手动替换乘法,因为编译器必须自动执行,移位运算符会降低可读性。我编写了一个简单的测试来检查这一点: 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): st

我看到一些建议(例如),你不应该用移位运算符手动替换乘法,因为编译器必须自动执行,移位运算符会降低可读性。我编写了一个简单的测试来检查这一点:

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")

怎么了?我的测试方法错了吗?时间测量错误吗?或者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 >>>dis.dis(λx:x*2) 1 0快速加载0(x) 3负载常数1(2) 6二进制乘法 7返回值
>>>dis.dis(lambda x:x此优化不会发生在字节码级别:

>>> 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 >>>dis.dis(λx:x*2) 1 0快速加载0(x) 3负载常数1(2) 6二进制乘法 7返回值 >>>dis.dis(lambda x:x使用(查看函数的字节码等价物)和(比使用
time
手动计时更可靠)可以让您更好地了解内部情况。测试脚本:

def multiply(x):
    return x * 2

def l_shift(x):
    return x << 1

def divide(x):
    return x // 2

def r_shift(x):
    return x >> 1

if __name__ == '__main__':
    import dis
    import timeit

    methods = (multiply, l_shift, divide, r_shift)
    setup = 'from __main__ import {}'.format(
        ', '.join(method.__name__ for method in methods),
    )
    for method in methods:
        print method.__name__
        dis.dis(method)
        print timeit.timeit(
            'for x in range(10): {}(x)'.format(method.__name__),
            setup=setup,
        )
        print
显然,Python没有用等价的位移位替换乘法/除法运算(例如,
BINARY\u loor\u DIVIDE
没有被
BINARY\u RSHIFT
替换),尽管看起来这样的优化可以提高性能。至于为什么位移动更快,请参见程序员。

使用(查看与函数等效的字节码)和(比尝试手动使用
时间进行计时更稳健)可以让您更好地了解内部情况。测试脚本:

def multiply(x):
    return x * 2

def l_shift(x):
    return x << 1

def divide(x):
    return x // 2

def r_shift(x):
    return x >> 1

if __name__ == '__main__':
    import dis
    import timeit

    methods = (multiply, l_shift, divide, r_shift)
    setup = 'from __main__ import {}'.format(
        ', '.join(method.__name__ for method in methods),
    )
    for method in methods:
        print method.__name__
        dis.dis(method)
        print timeit.timeit(
            'for x in range(10): {}(x)'.format(method.__name__),
            setup=setup,
        )
        print

显然,Python没有用等价的位移位替换乘法/除法运算(例如,
BINARY\u loor\u DIVIDE
没有被
BINARY\u RSHIFT
替换),尽管看起来这样的优化可以提高性能。至于为什么位移动更快,请参见程序员。

只有在非常有限的情况下,CPython才能实现这些优化。原因是CPython是一种被回避的类型化语言


给定代码片段
x*2
,这可能意味着非常不同的事情,取决于
x
的值。如果
x
是一个整数,那么它确实具有与
x相同的含义,只有在非常有限的情况下,CPython才能实现这些优化。原因是CPython是一种被回避的类型化语言


给定代码片段
x*2
,根据
x
的值,这可能意味着非常不同的事情。如果
x
是一个整数,那么它确实具有与
x相同的含义,您可以使用它来查看字节码,并获得更精确的计时。“我看到一些建议,不应该用移位运算符手动替换乘法,因为编译器必须自动执行,移位运算符会降低可读性。"-您在哪里看到这些建议?例如,想知道为什么在运行100次时要除以10。您在Unix上吗?Python是字节码解释的,字节码是源代码的表示形式,不应进行优化。优化可能发生在运行时。例如,在创建LLVM-IR时,LLVM不会创建此移位操作。当所有的东西都进入CPU并创建真正的指令时,这就是为什么你看到这些优化,例如C和C++编译器和JIT,而不是CPython。你可以用来查看字节码,并获得更精确的时序。“我看到一些建议,不应该用移位运算符手动替换乘法,因为编译器必须自动执行,移位运算符会降低可读性。"-您在哪里看到这些建议?例如,想知道为什么在运行100次时要除以10。您在Unix上吗?Python是字节码解释的,字节码是源代码的表示形式,不应进行优化。优化可能发生在运行时。例如,在创建LLVM-IR时,LLVM不会创建此移位操作。当所有的东西都进入CPU,并创建真正的指令时,这就是为什么你看到这些优化,例如C和C++编译器和JIT,而不是CPython。也许你可以更详细地解释这是什么。也许你可以更详细地解释一下这是什么。
In [3]: import dis

In [4]: def f():
   ...:     return 2 * 2
   ...: 

In [5]: dis.dis(f)
  2           0 LOAD_CONST               2 (4)
              3 RETURN_VALUE