8

なぜ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正しく使用しましたか?
  • 他の質問の結果がほぼ250%異なっていたのに、なぜこれらの結果は互いに0.1%少ない違いがあるのですか?
  • CPythonでコンパイルされたバージョンのPython(Cythonなど)を使用する場合にのみ違いがありますか?
  • 最終的に:Pythonコードは関数内で本当に高速ですか、それとも時間の調整方法に依存しますか?
4

2 に答える 2

11

あなたのテストの欠陥は、あなた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た最適化されていないコンパイルと比較して、問題の関数を使用したテストを次に示します。stmtf_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
于 2013-03-08T07:00:57.720 に答える
1

それはコンパイラ最適化アルゴリズムに帰着します。ジャストインタイムコンパイルを実行する場合、関数内で頻繁に使用されるコードのチャンクが見つかった場合、それらを識別するのははるかに簡単です。

効率の向上は、実際には実行されているタスクの性質に依存します。あなたが与えた例では、あなたは実際には計算集約的なことを何もしておらず、最適化によって効率を上げる機会が少なくなっています。

ただし、他の人が指摘しているように、CPythonはジャストインタイムコンパイルを実行しません。ただし、コードをコンパイルすると、Cコンパイラはコードをより高速に実行することがよくあります。

GCCコンパイラでこのドキュメントをチェックしてください:http://gcc.gnu.org/onlinedocs/gcc/Inline.html

于 2013-03-08T05:51:39.373 に答える