2013-03-08 9 views
7

私は質問Why does Python code run faster in a function?につながるコメントを見ました。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.9 
  • は私が正しくtimeitを使用しましたか?
  • なぜこれらの結果はお互いに0.1%未満であるのに対し、他の質問の結果はほぼ250%異なるのですか?
  • CPython Pythonのコンパイル済みバージョン(Cythonなど)を使用する場合にのみ違いがありますか?
  • 最終的には:Pythonコード実際にはが速くなっていますか、それとも時間の経過によりますか?
+1

:機能f_no_optで実行最適化されていないコンパイルstmtf_optとしてここ

は、問題のあなたの機能を備えたテストですPython対CPythonなど)が重要です)。また、適切な比較のために、他の質問と同じコードを実行してみてください(同じタイミングでタイミングを取る)。 – Cornstalks

+1

[この記事](http://stackoverflow.com/a/11241708/1961486)は洞察力があります。 – Octipi

+0

コンパイルされたバージョンのPython(CPython、PyPyなど)では問題ないようですが、普通の古いバニラのPythonでは違いはありません。 –

答えて

10

テストで欠陥が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)を使用して、関数で実行されています。私は通常、すなわち(そのバージョンと配布の両方(これは実装に大きく依存だと思う

>>> 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 
+0

これは素晴らしいことであり、Pythonの内部の仕組みを詳細に理解しています。あなたの経験では、これは(最適化段階で)コード化する方法に影響を及ぼしますか? –

+2

優れた設計では、関数を使用してグローバル変数の使用を最小限に抑えることが求められていますが、スピードを必要とするタイトなループでグローバル変数にアクセスすることは絶対に避けてください。 wikiには、[PythonSpeed](http://wiki.python.org/moin/PythonSpeed)のアドバイスがあります。 – eryksun

1

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

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

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

はGCCコンパイラでこの文書をチェックアウト:http://gcc.gnu.org/onlinedocs/gcc/Inline.html

+0

これはCPython(これはコンパイルされているので)に当てはまりますが、バニラのPythonではそうではないと思われます。 –

+0

@WesleyBaugh:Wait ... CPythonは "vanilla" Pythonと同じではありませんか?または、 "バニラ"のpythonの何か他のですか? –

+0

CPythonはほとんど最適化を行いません。最適化の程度は、無駄なロードとストアを取り除くことです。 CPythonはJITを持たず、インタプリタとして順次バイトコードを実行するだけです。 (PyPy、IronPython、Jythonなど、他の多くの実装ではそうではありません。これらはすべてJITをサポートしています)。 – nneonneo

関連する問題