Pythonコードの実行処理時間を計測する方法のイメージ画像

Pythonコードの実行処理時間を計測する方法

  • 公開日:2018/11/07
  • 更新日:2018/11/07
  • 投稿者:n bit

Pythonで大容量データなどを扱うようになるとコードの実行処理時間を早めるためのパフォーマンスチューニングも重要。改良を行うために最初はどこにボトルネックがあるのかの把握から。そのため今回はPythonコードの実行処理時間計測する方法について解説します。

  • Python

この記事は約 分で読めます。(文字)

Pythonコードの実行処理時間改善は計測から

自然言語解析や機械学習などを行うようになると膨大なデータが必要となります。膨大なデータの実行処理には時間を要しますがコードの記述方法1つでかなり改善されるケースも少なくありません。

CythonやNumba等のモジュールやC++などへの置き換えといった高速化の方法もありますが、まずは標準的なPythonの記述方法で対策した方が管理も楽になりますので覚えておきましょう。

コードの記述方法の改善に取り組むにあたってまず最初に必要となるのは『現在どれぐらいの処理時間がかかっているのか?』、『ボトルネックはどのコードにあるのか?』、『メモリーの状況はどうか?』といった問いに対して客観的に答えることができるように現状を把握することが実行処理時間の早いコードへ改善していく近道となります。

  • 現在の実行処理時間はどれぐらいか?
  • ボトルネックとなっているコードはどこか?
  • メモリーの使用やリーク状況はどうか?

コードの実行処理時間を実際に計測する方法は外部のモジュール等含めいくつかの方法がありますが、今回は最も簡単でかつ汎用性の高い方法を解説していきます。

実行処理時間の計測方法の種類

Pythonで選択することができる実行処理時間の計測方法を紹介しておきます。

timeやdatetimeモジュールを利用した実行処理時間の計測

今回解説する方法はこちらの方法になります。timeモジュールやdatetimモジュールを利用してスタート時間とプログラムの実行処理が完了した時間を差し引いて計算することでそれぞれの実行処理を計測することができます。

こちらの計測方法のメリットは標準のモジュールを利用するだけで完了できますので特別なインストール作業も不要で、かつ1行単位でも関数単位でもファイル単位でも自由に計測場所を設定することができることです。

デコレーターを利用した実行処理時間の計測

事前に計測用デコレータを作成しておき関数単位でデコレータを割り当て計測を行うことができます。

このやり方のメリットは記述するコード量が減ることです。1つのデコレータを用意しておけばそれぞれの関数に割り当てることができますので使い回しや計測場所の追加等が簡単にできます。

関数単位で複数計測したい場合はこちらの方法が便利でしょう。

Linuxのtimeコマンドを利用した実行処理時間の計測

Linuxのtimeコマンドを利用して実行処理時間を計測することもできます。timeコマンドはコマンドの実行時間の計測やリソースの使用量を表示するコマンドです。

こちらの方法はファイル単位で実行処理時間を計測する場合、実行コマンドに追記するのみで計測することができます。

ファイル単位での計測で良い場合はこちらの方法で良いでしょう。

cProfileやline_profiler、memory_profiler等を利用した実行処理時間の計測

line_profilerや、memory_profilerは外部モジュールとなりますので使用するためにはインストール作業等が必要となりますが実行処理やメモリの状況などを詳しく計測することができます。

より詳細な計測が必要な場合はこれらを利用しましょう。

Jupyter Notebookでtimeitマジックを利用した実行処理時間の計測

通常のPythonファイルでは利用できませんが、Jupyter Notebookで作業しているのであればtimeitマジックを利用することで実行処理時間を計測することができます。

簡単に計測できますのでJupyter Notebookでデータ解析などを行っている場合は積極的に利用すると良いでしょう。

timeモジュールを利用した実行処理時間の計測方法

timeモジュールを利用した実行処理時間の計測方法の基本的な考え方はとてもシンプルです。下記のように実行処理を開始した時間を終了時間から差し引くことで処理にかかった時間を計測することができます。

  • 処理を終了した時間 - 処理を開始した時間 = 実行処理時間

これだけです。とっても簡単ですね。それでは実際にコードを記述してみましょう。

timeモジュールを利用した実行処理時間計測のサンプルコード

まずは1カ所だけ計測する場合のサンプルコードです。複数実行処理を計測する場所がある場合はこちらのコードを複製して増やしていくだけです。

from time import time


num_list = list(range(10000))

start1 = time()

for i in num_list:
print(i)

proc_time = time() - start1
print(proc_time)

出力結果

0




9999
0.006661653518676758

for文で10,000回ループさせるのにかかった実行処理時間の計測です。『0.006661653518676758  sec』かかりました。

計測方法はループ開始前に

start1 = time()

で現在の時間をセットし、ループ終了後に

proc_time = time() - start1

print(proc_time)

で完了時間から開始の時間を差し引いて実行処理時間を求めています。

特にサンプルコードまで必要ないかもしれませんが複数行にわたって実行処理を計測する場合のサンプルコードも下記に記述しておきます。

from time import time


start0 = time()

num_list = list(range(10000))

proc_time = time() - start0
print('list create time: ', proc_time)

start1 = time()

for i in num_list:
print(i)

proc_time = time() - start1
print('roop time: ', proc_time)

proc_time = time() - start0
print('all time: ', proc_time)

出力結果

list create time:  0.0003025531768798828

0



9999
roop time: 0.00610041618347168
all time: 0.006417036056518555

これで行単位や関数単位、ファイル単位など自由に一括で実行処理の計測時間を確認することができます。

今日のdot

先日、自然言語処理の学習用データとなるウィキペディアのダンプデータに対して前処理を行っているとき、最初何気なく書いたコードでは作業完了までに82日間要する計算となってしまいました。

最終的にコードを修正することで約27分にまで縮めることができたので無事に作業を終えることができましたが最初の段階では少し冷や汗ものです。

このように大容量のデータを扱うようになった場合コードちょっとした記述方法で大幅に処理時間が変わってきます。こまめに実行処理時間を計測しながら少しでも早いコードの記述方法をストックしていくように心がけましょう。