python - python 会检测无用的代码片段吗? (消除死代码)

标签 python

如果我编写这样的代码:

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/

相关文章:

python - 总是在异常时调用 python 调试器的好通用方法

python - 根据命令行参数调用 python 函数

python - 什么是变量注解?

python - 如何计算python输出的均值、众数、方差、标准差等?

Python Pandas 从列表中创建多个数据框

python - 评估预测的准确性

python - 为什么在 Google App Engine 上使用 XHTML2PDF 时我的图像不显示?

python - 如何在 tkinter 中找出 Canvas 文本对象的大小?

python - 追加具有不同第一维度的 numpy 数组

python - Pandas 以最高值(value)保持复制