誰がPythonの性能が悪いと言ったの?

8569 ワード

[転載は出典を明記してください]
最近、ネット上でPython、Shellスクリプト、C++を比較する人がいるのを見て、主にPythonの性能を持って話をしているのを見て、個人的には意味がないと思います.一つの言語にはどんな性能の問題があるのか、背後にある実装(標準ライブラリ、コンパイラ)がすべてを決定している.まるでc++とcの効率を比較したい人がいるようだ.また、Pythonはスクリプト言語と呼ばれていますが、スクリプトはバッチコマンドファイルを指し、shellコマンドの集合であり、pythonとはまったく階層ではありません.ツールの階層によって、適用される問題も異なります.異なるレベルのものを引っ張って比較すると、何の問題も説明できません.また、shellはforkを知っていて、彼はまだ何ができると言っていますか?:-).
以下ではまず冗談を言って、Pythonの性能問題を実例で検討します.
まず、Pythonはダイナミックプログラミング言語であり、主なハイライトは開発応用の効率を高めることである.彼はJava、perl、Rubyなどの言語と同類です.システム統合、Webアプリケーションなどのシステムを作る利器であり、最近では科学計算分野でも気前がいい(numpy,scipy,sci-kit learn).C/Cplusplusとは基本的に階層的な開発ツールではありません.彼らは下位システム(ベースライブラリ、os、ecosはc++で書かれているのか、組み込みシステムで使われているのか)をしています.多くのライブラリが提供する機能も基礎的です.しかし、Pythonのためにcやcppのモジュールを書くことができ、Pythonシステム全体の性能を高めることができます.
次にPythonの主な解釈器CPythonはC言語で実現され,異なるタイプ(dict,list)と関数で実現されるアルゴリズムが異なる.もしあなたのシステムが性能に敏感であれば、いくつかの内幕を理解しなければなりません.1つの関数が異なるパラメータを入力すると、性能が大きく異なる可能性があります.また、PythonインタプリタがPythonコードを実行する場合、1)コードファイルをロードする2)AST 3に翻訳する)bytecode 4)を生成してPVM(python virtual machine)上でbytecodeを実行し、PVMは実際にスタックベースの仮想マシンである.ここで、最初の3段階はファイルコード量を見て、一般的にmsレベルの消費について、無駄にしたくない場合はpython-O-m py_を使うことができます.compile xx.pyコマンド、xx.pyはまずxxにコンパイルする.pyoのバイトコード、python xxを呼び出します.pyo実行PVMはC言語で書かれた関数として簡単に想像できます.中には非常に大きなswitchがあり、bytecodeの内容によって、異なる動作を実行します.たとえば、libcのライブラリ関数を呼び出し、c言語のオープンファイル操作を実行するオープンファイルコマンドに遭遇します.実は多くの操作python bytecodeとc言語の間の性能の違いは小さいです.Pythonの多くの機能モジュールはCライブラリを直接実行しているからです.
再度、Pythonの広範な応用に従って、CPython解釈器の性能の問題は確かにますます深刻になって、特にデータマイニング、機械学習の分野の日に日に熱くなって、その中の多くの優秀なツールの実現はPythonでした.この問題を解決するために、Pythonコミュニティでは、数値計算のnumba、pythonで実現されるpython解釈器pytyなど、さまざまな解釈器が提案されています.彼らの主な目的はPythonを加速させることであり、JIT、LLVMが使われている.たとえばnumbaはpythonに新しいdecoratorを提供し、python関数を実行時にllvmライブラリを介してmachine codeに翻訳できるようにします.CPythonの現在の主な目的はPython解釈器のモデルになり、安定で信頼性の高い機能を提供する最も完全な解釈器の実現の参考になる.また、Pythonで実装されている機能モジュールの性能が重要な場合は、このモジュールをCythonでC言語コードに翻訳し、実行可能プログラムにコンパイルすることができます.もちろんCythonを使うと、pythonで外部のCライブラリを呼び出しやすくなり、システム全体の性能を保証することができます.そのため、多くのPythonシステムの実行はますます速くなりますが、Pythonが速くなったのではなく、後のサポートがますます強くなっています.
最後に、PythonはJavaに似た言語で、スクリプトと理解しないでください.最初はスクリプトとして理解していましたが、pythonはpythonコードを入力し、すぐに結果を見ることができるコマンドラインツールを提供していたからかもしれません.実は、これはpythonがあなたに提供した優秀なツールの一つにすぎません.Pythonの各分野での使用はますます広がり、オープンソース資源もますます増えている:1.大規模な分布式計算discoはhadoopと類似のmapreduceモデルを提供するhttp://discoproject.org/2.科学計算/可視化numpy,scipy,matplotlib 3.データマイニングorange,sci-kit learn scikit-learn.sourceforge.net 4. Web開発djangoプロジェクトのすべてのIT分野では、Pythonの痕跡がほとんど見つかります.
このように多く言って、1つのテキスト処理の例を挙げて、テキストの中の第3列のデータの和を計算して、Pythonの功力を見てみて、特に性能の方面の問題、対比の参考はawk神器で、実はawkを対比するのは公平ではありませんて、結局awkは最適化の再最適化のツール(彼の実現を見る動力がなくて、私は推測します:))で、自分でc言語のバージョンを書くべきです.
サンプルファイルは1000万行あり、フォーマットは以下の通り:data.txt: d0 sp 0 d1 sp 1 d2 sp 2 d3 sp 3 d4 sp 4 d5 sp 5 d6 sp 6 d7 sp 7 d8 sp 8 d9 sp 9
まずawkの結果を見ます:$time cat data.txt |awk '{ sum+=$3} END {print sum}'49976634308700
real 0m3.662suser 0m3.576ssys 0m0.240s
1000万行3秒、やはり効率が高い.
Pythonを見て、4つのバージョンを作りました.Pythonコードバージョン(1):
import sys



def data_sum():

        datasum = 0

        for line in sys.stdin:

                raw = line.split()

                datasum += int(raw[2],10)

        print datasum



if __name__ == "__main__":

        data_sum()

 
Pythonコードバージョン(2):
import sys



def data_sum():

        datasum = 0

        for line in sys.stdin:

                raw = line.split()

                datasum += int(raw[2])

        print datasum



if __name__ == "__main__":

        data_sum()

~                        

 
Pythonコードバージョン(3):
def data_sum():

 datasum = 0

 for line in sys.stdin:

   datasum += int(‘2’,10)

print datasum



if __name__ == "__main__":

 data_sum()

 
Pythonコードバージョン(4):
import sys



def data_sum():

 datasum = 0

 for line in sys.stdin:

  raw = line.split()

 print datasum



if __name__ == "__main__":

 data_sum()

 
バージョン(1)実行結果:まずpythonコードをバイトコードにコンパイルし、$python-O-m py_を実行compile datasum.py$ time cat data.txt |python datasum.pyo 49976634308700
real 0m7.151suser 0m7.088ssys 0m0.192s
pythonコード$time cat dataを直接実行してみます.txt |python datasum.py49976634308700
real 0m7.323suser 0m7.228ssys 0m0.212s
2つの方法にはミリ秒レベルの違いがあり、主にcpythonがpythonコードをastに翻訳する段階で消費され、興味があれば自分でcpython検証をコンパイルすることができます.
そしてpypy、彼のJITとstacklessの効果を見てみましょう.$time cat data.txt | pypy-c datasum.py49976634308700
real 0m4.649suser 0m4.556ssys 0m0.224s
どうですか.awkバージョンより1秒遅いです.私はもうとても満足しています.他のバージョンを試してみましょう.ついでにPythonがどこに遅いのか見てみましょう.
バージョン(2):$time cat data.txt |python datasum.py49976634308700
real 0m9.111suser 0m9.025ssys 0m0.220s
$ time cat data.txt | pypy-c datasum.py49976634308700
real 0m4.694suser 0m4.588ssys 0m0.248s
バージョン(2)は直接バージョン(1)より2秒遅い.baseパラメータが1つ足りないだけで、Cpythonのコードを見るとわかります(Python/bltinmodule.c).
base付き、ダイレクトコール:x=PyOS_strtol(s, &end, base);
ベースなしでPyNumber_を通過するにはIntなどの内部タイプ処理関数の列があり、最後にPyOS_に到着した.strtol.
バージョン(3):$time cat data.txt |python datasum.py20000000
real 0m3.127suser 0m3.044ssys 0m0.188s
$ time cat data.txt | pypy-c datasum.py20000000
real 0m2.393suser 0m2.320ssys 0m0.196s
バージョン(4):$time cat data.txt |python datasum.py0
real 0m3.920suser 0m3.852ssys 0m0.180s
$ time cat data.txt | pypy-c datasum.py0
real 0m3.324suser 0m3.208ssys 0m0.252s
バージョン(3)とバージョン(4)を比較すると,Pythonは主にsplit関数,すなわち3列目の抽出という動作に遅いことが分かった.初歩的に考えてみると、C言語では確かにもっと速くできるが、Pythonでは良い方法が思いつかず、正規表現がもっと遅い.
上はすべてPythonの解釈器でコードを実行して、下はバージョン(1)をCythonでC言語にコンパイルして、効果を見てみます:$cython--embed-o datasum.c datasum.py$ gcc -o datasum datasum.c -I/usr/include/python2.7 -lpython2.7$ time cat data.txt |./datasum49976634308700
real 0m6.332suser 0m6.272ssys 0m0.192s
pypyよりも遅いですが、pyはコード生成に最適化されています.cythonは基本的にtranslateです.
まとめると、Pythonは高速プロトタイプ開発の利器であり、性能に要求があれば、彼の様々な最適化を使って、Pythonはあなたを裏切らない.あなたのリーダー/お客様があなたに大きなdeadlineの圧力を与えたとき、Pythonはあなたの救命草で、ほほほ.もちろん、いくつかの簡単な機能、例えば本文の例はawkでいいですか.pythonを最適化するのに苦労しています.