我正在优化一些 Python 代码,并尝试了以下实验:
import time
start = time.clock()
x = 0
for i in range(10000000):
x += 1
end = time.clock()
print '+=',end-start
start = time.clock()
x = 0
for i in range(10000000):
x -= -1
end = time.clock()
print '-=',end-start
第二个循环确实更快,从 mustache 到 10% 不等,具体取决于我运行它的系统。我已经尝试改变循环的顺序、执行次数等,但它似乎仍然有效。
陌生人,
for i in range(10000000, 0, -1):
(即向后运行循环)比
快for i in range(10000000):
即使循环内容相同。
提供了什么,这里有更通用的编程类(class)吗?
最佳答案
我可以在我的 Q6600 (Python 2.6.2) 上重现这个;将范围增加到 100000000:
('+=', 11.370000000000001)
('-=', 10.769999999999998)
首先,一些观察:
- 这是一个简单操作的 5%。这很重要。
- native 加法和减法操作码的速度无关紧要。它在本底噪声中,与字节码评估相比完全相形见绌。那是在谈论成千上万的一两个 native 指令。
- 字节码生成完全相同数量的指令;唯一的区别是
INPLACE_ADD
与INPLACE_SUBTRACT
和 +1 与 -1。
查看 Python 源代码,我可以做出猜测。这是在 ceval.c 中的 PyEval_EvalFrameEx
中处理的。 INPLACE_ADD
有一个重要的额外代码块,用于处理字符串连接。 INPLACE_SUBTRACT
中不存在该 block ,因为您不能减去字符串。这意味着 INPLACE_ADD
包含更多 native 代码。取决于(严重!)编译器生成代码的方式,这些额外的代码可能与 INPLACE_ADD 代码的其余部分内联,这意味着加法比减法更难命中指令缓存。这可能会导致额外的二级缓存命中,这可能会导致显着的性能差异。
这在很大程度上取决于您所在的系统(不同的处理器具有不同数量的缓存和缓存架构)、使用的编译器,包括特定的版本和编译选项(不同的编译器会以不同的方式决定哪些代码位是在关键路径上,它决定了汇编代码如何集中在一起),等等。
此外,Python 3.0.1 中的差异是相反的(+:15.66,-:16.71);毫无疑问,这个关键功能已经发生了很大变化。
关于python - 为什么减法比 Python 中的加法快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1396564/