Python是否优化循环中的函数调用?
比如说,我有一个代码,它从循环中调用某个函数数百万次,我希望代码速度更快:Python是否优化循环中的函数调用?,python,optimization,compiler-optimization,Python,Optimization,Compiler Optimization,比如说,我有一个代码,它从循环中调用某个函数数百万次,我希望代码速度更快: def outer_function(file): for line in file: inner_function(line) def inner_function(line): # do something pass 它不一定是一个文件处理,例如,它可以是从函数绘制线调用的函数绘制点。从逻辑上讲,这两者必须分开,但从性能的角度来看,它们应该尽可能快地协同工作 Python会
def outer_function(file):
for line in file:
inner_function(line)
def inner_function(line):
# do something
pass
它不一定是一个文件处理,例如,它可以是从函数绘制线调用的函数绘制点。从逻辑上讲,这两者必须分开,但从性能的角度来看,它们应该尽可能快地协同工作
Python会自动检测并优化这些东西吗?如果没有-有没有办法给它一个这样做的线索?使用一些额外的外部优化器?..调用函数来调用
pass
语句显然会带来相当高的成本(∞) 开销。你的实际程序是否受到不必要的开销取决于内部函数的大小。如果它真的只是设置一个像素,那么我建议使用一种不同的方法,使用以C语言或C++语言编写的绘图原语。
有一些(有些实验性的)Python JIT编译器可以优化函数调用,但主流Python不会这样做。如果你所说的“Python”是指普遍使用的实现,则不是
如果使用“Python”你说的是Python语言的任何实现,是的。可以进行很多优化,我相信它的方法JIT应该能够处理类似的情况。Python不内联函数调用,因为它是动态的。理论上,
内部函数
可以将名称内部函数
重新绑定到something else-Python无法在编译时知道可能发生这种情况。例如:
def func1():
global inner_func
inner_func = func2
print 1
def func2():
print 2
inner_func = func1
for i in range(5):
inner_func()
印刷品:
1
2
2
2
2
你可能认为这很可怕。然后,再想想——Python的功能性和动态性是它最吸引人的特性之一。Python允许的很多东西都是以性能为代价的,在大多数情况下这是可以接受的
也就是说,你可能可以使用类似的工具将一些东西组合在一起——将内部函数分解成字节码,插入外部函数,然后重新组装。再想一想,如果你的代码对性能要求很高,足以进行此类攻击,只需用C语言重写即可。Python对FFI有很好的选择
这一切都与官方的CPython实现有关。一个运行时JITting解释器(比如PyPy或不幸倒闭的unladenswallow)理论上可以检测正常情况并执行内联。唉,我对PyPy不太熟悉,不知道它是否能做到这一点,但它肯定能做到。哪种Python?PyPy的JIT编译器会在几百或几十次之后(取决于每次迭代执行多少操作码)迭代——开始跟踪执行,一路上忘记Python函数调用,将收集的信息编译成一段优化的机器代码,这段代码可能没有导致函数调用本身发生的任何逻辑残余。跟踪是线性的,JIT的后端甚至不知道有函数调用,它说只看到来自两个函数的指令在执行时混合在一起。(这是一个完美的例子,例如循环中存在分支或所有迭代都采用相同的分支。有些代码不适合这种JIT编译,并在它们产生很大加速之前使跟踪快速失效,尽管这是相当罕见的。) 现在,CPython,许多人在谈论“Python”时是什么意思或者Python解释器,它不是很聪明。它是一个直截了当的字节码VM,它将尽责地执行在每次迭代中一次又一次调用函数的逻辑。但是,如果性能是<强> > <强>重要的话,为什么还要使用解释器?考虑在原生代码中编写热循环。(例如,作为C扩展或in)如果保持尽可能低的开销非常重要 除非每次迭代只进行一点点的数字运算,否则无论如何都不会有很大的改进。CPython(“标准”python实现)不会进行这种优化 但是请注意,如果您正在计算函数调用的CPU周期,那么对于您的问题,CPython可能不是正确的工具。如果您100%确定您将要使用的算法已经是最好的(这是最重要的事情),并且您的计算确实是CPU受限的,则选项如下:
def func1():
global inner_func
inner_func = func2
print 1
def func2():
print 2
inner_func = func1
for i in range(5):
inner_func()
- 使用而不是CPython
- 使用
- 编写C++模块并与 接口
- 如果可能,使用simd方法实现您的算法
- 如果可能,在GPU硬件上移动计算,例如