非常に簡単です。Pythonスクリプト内から外部コマンド/プログラムを実行したいと思います。それが終了したら、CPU時間も知りたいと思います。
ハードモード:複数のコマンドを並行して実行しても、CPU消費の結果に不正確さが生じることはありません。
非常に簡単です。Pythonスクリプト内から外部コマンド/プログラムを実行したいと思います。それが終了したら、CPU時間も知りたいと思います。
ハードモード:複数のコマンドを並行して実行しても、CPU消費の結果に不正確さが生じることはありません。
UNIXの場合:(a)リソースモジュールを使用する(icktoofayによる回答も参照)か、(b)timeコマンドを使用して結果を解析するか、(c)/procファイルシステムを使用して/proc/ [pid]/statを解析します。解析しutime
てstime
フィールドを作成します。これらの最後はLinux固有です。
使用例resource
:
import subprocess, resource
usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)
subprocess.call(["yourcommand"])
usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)
cpu_time = usage_end.ru_utime - usage_start.ru_utime
注:fork / execvpを実行する必要はありません。そうでない場合subprocess.call()
、他のサブプロセスメソッドはここで問題なく、はるかに使いやすくなります。
注:subprocess.Popenまたはsubprocess.callとthreadsのいずれかを使用して、同じPythonスクリプトから複数のコマンドを同時に実行できますが、リソースは正しい個々のCPU時間を返さず、getrusageの呼び出し間の時間の合計を返します。 ; 個々の時間を取得するには、コマンドごとに1つの小さなPythonラッパーを実行して上記のように時間を計ります(メインスクリプトからそれらを起動できます)、または複数の同時コマンドで正しく機能する以下の方法を使用します(時間は基本的にそのようなラッパーですtime
)。
使用例time
:
import subprocess, StringIO
time_output = StringIO.StringIO()
subprocess.call(["time", "yourcommand", "youroptions"], stdout=time_output)
# parse time_output
Windowsの場合:何らかの方法でパフォーマンスカウンター(別名「パフォーマンスデータヘルパー」)を使用する必要があります。基盤となるAPIのCの例を次に示します。Pythonから取得するには、 win32pdh (pywin32の一部;サンプルコード)またはpyrfcon(クロスプラットフォーム、Unixでも動作します;サンプルコード)の2つのモジュールのいずれかを使用できます。
これらの方法はいずれも、実際には上記の「ハードモード」要件を満たしています。ビジー状態のシステムで異なるプロセスの複数のインスタンスが実行されている場合でも、正確である必要があります。その場合、プロセスの切り替えにはある程度のオーバーヘッドがあるため、アイドル状態のシステムで1つのプロセスだけを実行する場合とはまったく同じ結果が得られない場合がありますが、最終的にOSスケジューラからデータを取得するため、非常に近くなります。
利用可能なプラットフォームでは、resource
モジュールが必要なものを提供する場合があります。複数のコマンドの時間を同時に計測する必要がある場合は、(実行するコマンドごとに)フォークしてからサブプロセスを作成して、そのプロセスのみの情報を取得することができます。これを行う1つの方法は次のとおりです。
def start_running(command):
time_read_pipe, time_write_pipe = os.pipe()
want_read_pipe, want_write_pipe = os.pipe()
runner_pid = os.fork()
if runner_pid != 0:
os.close(time_write_pipe)
os.close(want_read_pipe)
def finish_running():
os.write(want_write_pipe, 'x')
os.close(want_write_pipe)
time = os.read(time_read_pipe, struct.calcsize('f'))
os.close(time_read_pipe)
time = struct.unpack('f', time)[0]
return time
return finish_running
os.close(time_read_pipe)
os.close(want_write_pipe)
sub_pid = os.fork()
if sub_pid == 0:
os.close(time_write_pipe)
os.close(want_read_pipe)
os.execvp(command[0], command)
os.wait()
usage = resource.getrusage(resource.RUSAGE_CHILDREN)
os.read(want_read_pipe, 1)
os.write(time_write_pipe, struct.pack('f', usage.ru_utime))
sys.exit(0)
次に、それを使用していくつかのコマンドを実行できます。
get_ls_time = start_running(['ls'])
get_work_time = start_running(['python', '-c', 'print (2 ** 512) ** 200'])
そのコードが実行された後、これらのコマンドの両方が並行して実行されている必要があります。それらが終了するのを待ち、実行にかかった時間を取得したい場合は、start_running
:によって返される関数を呼び出します。
ls_time = get_ls_time()
work_time = get_work_time()
これで、実行にかかった時間が含まれ、実行にかかったls_time
時間が含まれます。ls
work_time
python -c "print (2 ** 512) ** 200"
Python内でタイミングをとることはできますが、プログラムの全体的なCPU消費量を知りたい場合は、それを行うのはちょっとばかげています。最善の方法は、GNUtime
プログラムを使用することです。ほとんどのオペレーティングシステムにも標準装備されています。
Pythonのtimeitモジュールは、ベンチマーク/プロファイリングの目的で非常に役立ちます。それに加えて、コマンドラインインターフェイスから呼び出すこともできます。外部コマンドのベンチマークを行うには、次のようにします。
>>> import timeit
>>> timeit.timeit("call(['ls','-l'])",setup="from subprocess import call",number=1) #number defaults to 1 million
total 16
-rw-rw-r-- 1 nilanjan nilanjan 3675 Dec 17 08:23 icon.png
-rw-rw-r-- 1 nilanjan nilanjan 279 Dec 17 08:24 manifest.json
-rw-rw-r-- 1 nilanjan nilanjan 476 Dec 17 08:25 popup.html
-rw-rw-r-- 1 nilanjan nilanjan 1218 Dec 17 08:25 popup.js
0.02114391326904297
最後の行は、返される実行時間です。ここで、の最初の引数timeit.timeit()
は外部メソッドを呼び出すためのコードであり、setup
引数は時間測定の開始前に実行するコードを指定します。number
引数は、指定されたコードを実行する回数です。次に、返された時間を除算して、number
平均時間を取得できます。
timeit.repeat()
同様の引数をとるメソッドを使用することもできますtimeit.timeit()
が、追加のrepeat
引数を使用して、呼び出される回数を指定し、timeit.timeit()
各実行の実行時間のリストを返します。
注:メソッドによって返される実行時間はtimeit.timeit()
、CPU時間ではなく、実時間です。そのため、他のプロセスがタイミングを妨げる可能性があります。したがって、timeit.repeat()
平均または標準偏差を計算するのではなく、最小値を使用する必要があります。
これは、ipythonの%time
魔法の関数を使用して行うことができます:
In [1]: time 2**128
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.00
Out[1]: 340282366920938463463374607431768211456L
In [2]: n = 1000000
In [3]: time sum(range(n))
CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
Wall time: 1.37
Out[3]: 499999500000L