如果我编写这样的代码:
for _ in range(100_000_000):
a = 10
b = 20
c = a + b
d = c * 2
e = d / 2
del a, b, c, d, e
print("Hello World")
Python编译器会意识到它是无用的并且不需要做任何事情吗?我听说 gcc 可以理解,但 Python 不能。
我的测试证实了这一点,但我正在寻找确认,因为我偶然发现了这样的帖子( https://bugs.python.org/issue1346214 ),这让我想知道它是否真正实现了。这是一个非常旧的 Python 版本,我正在使用 3.11.1,但如果他们已经在谈论它,我确定他们是否要实现它,现在已经实现了?
在我的笔记本电脑上,Python 代码需要 0.07 秒才能运行 0 秒,仅显示 hello world,这就是为什么我认为没有死代码消除。
最佳答案
它并没有消除无用的代码,你可以向自己证明这一点 - 比较 slow
中的反汇编代码与 fast
中的反汇编代码,你会发现它确实如此确实做了所有这些无用的计算。您还可以使用 timeit
验证它们是否正在运行。但这仅适用于 cpython
- python 的其他实现可能会对此进行优化(正如您在下面使用 numba
的 python 子集所看到的!)
import dis
import timeit
def slow():
for _ in range(100_000_000):
a = 10
b = 20
c = a + b
d = c * 2
e = d / 2
del a, b, c, d, e
print("Hello World")
def fast():
print("Hello World")
print(timeit.timeit('slow()',number=1000,globals=globals()))
dis.dis(slow)
print("*****")
print(timeit.timeit('fast()',number=5,globals=globals()))
dis.dis(fast)
产量:
39.3209762
3 0 LOAD_GLOBAL 0 (range)
2 LOAD_CONST 1 (100000000)
4 CALL_FUNCTION 1
6 GET_ITER
>> 8 FOR_ITER 46 (to 56)
10 STORE_FAST 0 (_)
4 12 LOAD_CONST 2 (10)
14 STORE_FAST 1 (a)
5 16 LOAD_CONST 3 (20)
18 STORE_FAST 2 (b)
6 20 LOAD_FAST 1 (a)
22 LOAD_FAST 2 (b)
24 BINARY_ADD
26 STORE_FAST 3 (c)
7 28 LOAD_FAST 3 (c)
30 LOAD_CONST 4 (2)
32 BINARY_MULTIPLY
34 STORE_FAST 4 (d)
8 36 LOAD_FAST 4 (d)
38 LOAD_CONST 4 (2)
40 BINARY_TRUE_DIVIDE
42 STORE_FAST 5 (e)
9 44 DELETE_FAST 1 (a)
46 DELETE_FAST 2 (b)
48 DELETE_FAST 3 (c)
50 DELETE_FAST 4 (d)
52 DELETE_FAST 5 (e)
54 JUMP_ABSOLUTE 8
10 >> 56 LOAD_GLOBAL 1 (print)
58 LOAD_CONST 5 ('Hello World')
60 CALL_FUNCTION 1
62 POP_TOP
64 LOAD_CONST 0 (None)
66 RETURN_VALUE
*****
8.899999997424857e-06
13 0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('Hello World')
4 CALL_FUNCTION 1
6 POP_TOP
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
如果您确实想通过优化真正提高 Python 速度,请查看 numba
:
import numba as nb
import timeit
@nb.jit
def slow():
for _ in range(100_000_000):
a = 10
b = 20
c = a + b
d = c * 2
e = d / 2
print("Hello World")
@nb.jit
def fast():
print("Hello World")
print(timeit.timeit('slow()',number=5,globals=globals()))
print(timeit.timeit('fast()',number=5,globals=globals()))
print(slow.inspect_llvm()[tuple()])
print("****")
print(fast.inspect_llvm()[tuple()])
这些将产生非常相似的 LLVM 代码。不过,numba
编译的代码存在许多限制,超出了本问题的范围。
关于python - python 会检测无用的代码片段吗? (消除死代码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76501826/