トップページに戻る
pythonの高速化
注: pythonの長所はあくまでも、プログラムを簡単に作成、実行できる点です。
さまざまな工夫を使って高速化する必要がある場合は、コンパイル言語を使って実装しなおすほうが良いこともあります
pythonは基本的にインタプリタ型言語であり、実行時にテキストのソースプログラムを機械語に翻訳しながら実行します。
また、オブジェクト指向言語であり、全ての関数、変数はオブジェクトとして扱われます。多くのスクリプト言語
(あるいは Light Weight Language: LWL) と同様、
pythonのオブジェクトは辞書型変数 (__dict__)
が実体です。そのため、オブジェクトのattributeへのアクセスは非常にオーバーヘッドが大きくなります。
それに対し、C/C++で実装されている組み込み構文・関数やモジュールの実行速度は格段に速くなります。以下の注意を払うことで
pythonプログラムの高速化ができるかもしれません。
- 同じ機能があるのであれば、なるべく組み込み構文・関数、C/C++で実装されているモジュールを使う。
・ ブロック型for文の代わりに、リスト内包表記を使う。ループ変数を参照する必要がない場合は
_ 変数をループ変数とする。
・
for文の代わりに、sum()やmap()などの組み込み関数を使う
- 頻繁に参照するオブジェクト変数は局所変数に代入して使う
- 不要な型変換を減らす
・
ファイル変換を行う際、数値をテキストファイルから読み込み、浮動小数点型に変換してから出力テキストファイルに書き出すのは無駄です。
文字列型のまま処理をします。
・ 不要な整数型への型変換をしないことは、浮動小数点
=> 整数
変換の際の丸め誤差を避ける意味でも有効です。
- 大きな数値テーブルを読み込む場合、numpy.load_txt() や
pandas.load_csv() を使うより、組み込み関数 read()/readlines()
を使う方がはるかに高速です。
これは、load_txt()/load_csv() などでは、自動的にnumpy.ndarray()やpandas.DataFrame()に変換されるため、型変換のオーバーヘッドが大きいためと思われます。
読み込んだ数値を計算に使用する場合には load_txt()/load_csv()
が必要になりますが、ファイル変換だけの場合は、read()/readlines()で読み込んだ文字列を、文字列のまま処理すべきです。
- 細かい文字列変数の結合を繰り返さない。
メモリー領域の取得はオーバーヘッドの大きい作業です。例えば、テキストファイルを1行ずつ読み込んで、そのたびに文字列型に連結するような
操作は、頻繁にメモリー領域の取得・解放・コピーを繰り返し、遅くなります。
・ ファイルをすべて文字列変数に読み込む場合は、read()
関数で読み込む
・
多数の文字列を連結する場合、リスト変数にいれて、最後に
"".join() 関数を使う (方が早いかもしれない。bench
markでの確認はしていません)
- matplotlibを使ってアニメーションをする場合、FuncAnimationを使うとオーバーヘッドが高いようです。
また、グラフをax1.clear()で初期化して作り直すよりも、更新されるデータのみ
line1.set_data(xeq, x - xeq) のように更新して
plt.pause(0.001)
で再描画する方が圧倒的に速くなります。以下の実行を比較してみてください。
FuncAnimation: md_osscilators_FuncAnimation.py
set_data+pause: md_osscilators_pause.py
set_data+pauseの方が計算条件が厳しいですが、それでも実行速度が速いです
- Nukitaにより実行可能ファイルにコンパイルする
- Numbaモジュールを使う
ただし、上記のような工夫
(C/C++などで書き直すことを除く)
をしたとしても、実行速度はコンパイル言語にはまったくかないません。
- Mojo, PyPy, Cythonなど、互換性の高いコンパイル言語を使う
- C/C++で書き、pythonから呼び出す
スクリプト言語と比較しても、例えば、オブジェクトを使わないperlと比べても数分の1の速度になります
(perlでオブジェクト変数アクセスを主にするとpythonと同程度まで遅くなります)。
注: pythonのコードをバイトコンパイルすこともできます。ただし、オブジェクトにattributeを動的に追加したり、eval()
を使うコードには事前コンパイルは機能しません。
参考: Pythonのコードをバイトコンパイルする方法
注:
pythonではバージョンアップによって実行速度が改善されていることがあります。
注: python3.13から Just in time
コンパイラの実装が始まりました。まだ十分な性能は出ていないようですが、将来的には高速化される可能性があります。