1

次のような関数を定義した場合:

def ccid_year(seq):
  year, prefix, index, suffix = seq
  return year

Pythonはそれを効果的に最適化することができますか:

def ccid_year(seq):
  return seq[0]

渡されるデータの形式を文書化するため、最初の関数を作成したいと思いますが、Python が 2 番目の定義と同じくらい効率的なコードを生成することを願っています。

4

2 に答える 2

3

後で額面通りに質問に答えますが、最初に:疑問がある場合は、ベンチマークしてください。ただし、最初に、ほとんどの時間がコードのごく一部に費やされていることを思い出してください(つまり、ほとんどのコードはパフォーマンスとは無関係です!)。CPythonでは、関数呼び出しのオーバーヘッドが通常、小さな非効率性を支配します。言うまでもなく、大規模なアルゴリズムの非効率性(別名、おかしな愚かなコード)は、マイクロ最適化の懸念を小さくします。

したがって、これについてはまったく心配しないでください。または、心配する理由がある場合は、最初のベンチマークの選択肢と2番目のベンチマークを関数に入れないでください。「心配する理由」は、心配するのに費やした時間と、手動最適化の保守負担(ある場合)に対して重み付けする必要があることに注意してください。

最もよく使用するリファレンス実装であるCPythonは、このレベルでの最適化について非常に保守的です。バイトコードで動作するのぞき穴オプティマイザがありますが、規模には制限があります。より一般的には、単一のステートメントにまたがる多くの最適化は期待できません。Pythonコードを静的に最適化する際の問題は、最も無邪気に見えるプログラムframentでさえ、任意のコードを呼び出すことができる方法が何十億もあることです。私たちがそれに取り組んでいる間、提案された最適化は無効です(プログラムが同じ動作をしないという意味で)seq間違ったタイプ(シーケンスではない、または非常に奇妙なシーケンスではない)または長さ(正確に3つのアイテムの長さではない)です!Pythonを実装すると主張するプログラムは、そのような違いを維持する必要があるため、文字通り提案した変換は実行されません。これは単なる手に負えない図だと思いますが、Pythonがどれほど複雑であるかを真剣に過小評価していることを示しています(実装するため、そして最適化するために二重に)。私や他の人はこれについて以前に詳しく書いたので、この投稿がさらに大きくなる前にここでやめます。

一方、PyPyは、この関数が実際にホットループから呼び出された場合、Pythonループよりも高速に反復するマシンコードループにコンパイルしながら、おそらくこれとあなたが考えもしなかった他の何百万ものものを最適化しますCPythonで繰り返すことができます。ループから抜け出し、必要に応じて適切なアクション(例外の発生など)を実行するためのチェックがいくつか含まれていますが、トリガーされない場合は非常に効率的です。

IronPythonとJython、およびその他の実装についてはよくわかりませんが、CPythonよりも数倍速いベンチマーク結果が一貫していないことが何らかの指標である場合、それらは重要な最適化を実行しません。VM IronPythonとJythonにはJITコンパイラが含まれていますが(PyPyとはまったく異なりますが、完全に異なります)、これらのJITコンパイラは非常に異なる言語用に構築されているため、IronPython/Jythonのコードの混乱を調べることができれば非常に驚きます。 Pythonセマンティクスを実現し、そのような最適化を実行するには、実行する必要があります。

于 2013-02-14T18:33:37.070 に答える
3

2 つの関数は同等ではありません。

def ccid_year_1(seq):
  year, prefix, index, suffix = seq
  return year

def ccid_year_2(seq):
  return seq[0]

arg = {1:'a', 2:'b', 0:'c', 3:'d'}
print ccid_year_1(arg)
print ccid_year_2(arg)

最初の呼び出し0で表示され、2 番目の呼び出しで表示されcます。

于 2013-02-14T18:37:32.927 に答える