Python代码在函数中运行速度真的更快吗?



我看到一个注释,让我想到为什么Python代码在函数中运行得更快?

我开始思考,并认为我会尝试自己使用timeit库,但我得到了非常不同的结果:

(注释: 10**8被更改为10**7以使事情更快一点)

>>> from timeit import repeat
>>> setup = """
def main():
    for i in xrange(10**7):
        pass
"""
>>> stmt = """
for i in xrange(10**7):
    pass
"""
>>> min(repeat('main()', setup, repeat=7, number=10))
1.4399558753975725
>>> min(repeat(stmt, repeat=7, number=10))
1.4410973942722194
>>> 1.4410973942722194 / 1.4399558753975725
1.000792745732109
  • 我使用timeit正确吗?
  • 为什么这些结果相差不到0.1%,而另一个问题的结果相差近250% ?
  • 它只在使用CPython编译版本的Python(如Cython)时产生差异吗?
  • 最终:Python代码在函数中真的更快吗,还是仅仅取决于你如何计时?

测试中的缺陷是timeit编译stmt代码的方式。它实际上是在以下模板中编译的:

template = """
def inner(_it, _timer):
    %(setup)s
    _t0 = _timer()
    for _i in _it:
        %(stmt)s
    _t1 = _timer()
    return _t1 - _t0
"""

因此,stmt实际上是运行在一个函数中,使用fastlocals数组(即STORE_FAST)。

下面是一个测试,问题中的函数作为f_opt与未优化编译的stmt在函数f_no_opt中执行:

>>> code = compile(stmt, '<string>', 'exec')
>>> f_no_opt = types.FunctionType(code, globals())
>>> t_no_opt = min(timeit.repeat(f_no_opt, repeat=10, number=10))
>>> t_opt = min(timeit.repeat(f_opt, repeat=10, number=10))
>>> t_opt / t_no_opt
0.4931101445632647

归根结底是编译器优化算法。在执行即时编译时,如果在函数中找到频繁使用的代码块,那么识别它们就容易得多。

效率的提高实际上取决于正在执行的任务的性质。在您给出的示例中,您实际上没有做任何计算密集型的事情,因此通过优化获得效率增益的机会更少。

然而,正如其他人指出的那样,CPython不进行即时编译。然而,当代码被编译时,C编译器通常会更快地执行它们。

在GCC编译器上查看此文档:http://gcc.gnu.org/onlinedocs/gcc/Inline.html

相关内容

  • 没有找到相关文章

最新更新