为什么 a=a*100 比 a*=100 快两倍?

Ste*_*611 17 python numpy

继有关链接 *= += 运算符的问题Tom Wojcik 的好评“你为什么假设aaa *= 200比 快aaa = aaa * 200 ”)之后,我在 Jupyter notebook 中对其进行了测试:

%%timeit aaa = np.arange(1,101,1)
    aaa*=100

%%timeit aaa = np.arange(1,101,1)
    aaa=aaa*100
Run Code Online (Sandbox Code Playgroud)

我很惊讶,因为第一个测试比第二个测试长:分别为 1530ns 和 952ns。为什么这些价值观如此不同?

Kir*_*hou 13

TL;DR:这个问题相当于inplace_binop (INPLACE_*) (aaa*=100)binop (BINARY_*) 之间的性能差异(aaa=aaa*100)。可以通过使用dis模块找到差异:

import numpy as np
import dis

aaa = np.arange(1,101,1)
Run Code Online (Sandbox Code Playgroud)
dis.dis('''
for i in range(1000000):
  aaa*=100
''')
Run Code Online (Sandbox Code Playgroud)
  3          14 LOAD_NAME                2 (aaa)
             16 LOAD_CONST               1 (100)
             18 INPLACE_MULTIPLY
             20 STORE_NAME               2 (aaa)
             22 JUMP_ABSOLUTE           10
        >>   24 POP_BLOCK
        >>   26 LOAD_CONST               2 (None)
             28 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
  3          14 LOAD_NAME                2 (aaa)
             16 LOAD_CONST               1 (100)
             18 INPLACE_MULTIPLY
             20 STORE_NAME               2 (aaa)
             22 JUMP_ABSOLUTE           10
        >>   24 POP_BLOCK
        >>   26 LOAD_CONST               2 (None)
             28 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
  3          14 LOAD_NAME                2 (aaa)
             16 LOAD_CONST               1 (100)
             18 BINARY_MULTIPLY
             20 STORE_NAME               2 (aaa)
             22 JUMP_ABSOLUTE           10
        >>   24 POP_BLOCK
        >>   26 LOAD_CONST               2 (None)
             28 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

然后回到你的问题,哪个绝对更快?

不幸的是,很难说哪个函数更快,原因如下:

您可以直接查看CPython代码的compile.c。如果您稍微追溯一下 CPython 代码,就会发现函数调用的不同之处:

  • inplace_binop -> compiler_augassign -> compiler_visit_stmt
  • binop -> compiler_visit_expr1 -> compiler_visit_expr -> compiler_visit_kwonlydefaults

由于函数调用和逻辑不同,这意味着有很多因素(包括您的输入大小(*)、CPU...等)也可能对性能产生影响,您需要进行分析以优化您的基于您的用例的代码。

*:来自其他评论,您可以查看此帖子以了解不同输入大小的性能。


Pet*_*lla 7

+= 符号出现在 1970 年代的 C 语言中,而 - 与“智能汇编器”的 C 思想对应的是明显不同的机器指令和寻址方式

"a=a * 100" "a *= 100" 产生相同的效果,但在低级别对应于处理器的不同工作方式。

a *= 100 方法

  • 找到由 a 标识的地方
  • 乘以100

a = a * 100 方法:

  • 评估 a*100
  • 找到由 a 标识的地方
  • 将 a 复制到累加器中
  • 将累加器乘以 100
  • 将结果存储在一个
  • 找到由 a 标识的地方
  • 将累加器复制到它

Python 是用 C 编码的,它继承了 C 的语法,但由于在解释语言执行之前没有翻译/优化,所以事情不一定如此密切相关(因为少了一个解析步骤)。然而,解释器可以为三种类型的表达式引用不同的执行例程,根据表达式的形成方式和计算上下文利用不同的机器代码。