7

非常に簡単です。Pythonスクリプト内から外部コマンド/プログラムを実行したいと思います。それが終了したら、CPU時間も知りたいと思います。

ハードモード:複数のコマンドを並行して実行しても、CPU消費の結果に不正確さが生じることはありません。

4

5 に答える 5

17

UNIXの場合:(a)リソースモジュールを使用する(icktoofayによる回答も参照)か、(b)timeコマンドを使用して結果を解析するか、(c)/procファイルシステムを使用して/proc/ [pid]/statを解析します。解析しutimestimeフィールドを作成します。これらの最後は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スケジューラからデータを取得するため、非常に近くなります。

于 2012-12-18T13:11:38.203 に答える
4

利用可能なプラットフォームでは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時間が含まれます。lswork_timepython -c "print (2 ** 512) ** 200"

于 2012-12-15T05:43:29.250 に答える
3

Python内でタイミングをとることはできますが、プログラムの全体的なCPU消費量を知りたい場合は、それを行うのはちょっとばかげています。最善の方法は、GNUtimeプログラムを使用することです。ほとんどのオペレーティングシステムにも標準装備されています。

于 2012-12-15T03:42:23.820 に答える
2

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()平均または標準偏差を計算するのではなく、最小値を使用する必要があります。

于 2012-12-17T05:23:08.497 に答える
1

これは、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
于 2012-12-15T03:59:29.367 に答える