3

いくつかのセキュリティ ソフトウェアをテストするには、Windows で大量の (構成可能な) 多数の新しいプロセス (スレッドではない!) を非常に迅速に作成し、(構成可能な) 一定期間存在させてから、正常に終了できる必要があります。 . プロセスは何もしないでください。指定された期間だけ存在します。

最終的には、次のようなものを実行できるようにしたいと考えています。

C:\> python process_generate.py --processes=150 --duration=2500

これにより、150 個の新しいプロセスが非常に迅速に作成され、それらすべてが 2500 ミリ秒の間存続し、その後すべてができるだけ早く終了します。

出発点として、私は走った

from multiprocessing import Process
import os

def f():
    pass

if __name__ == '__main__':
    import datetime
    count = 0
    startime = datetime.datetime.now()
    while True:
        p = Process(target=f)
        p.start()
        p.terminate()
        count += 1
        if count % 1000 == 0:
            now = datetime.datetime.now()
            print "Started & stopped d processes in %s seconds" % (count, str(now-starttime))

そして、ラップトップで毎秒約 70 プロセスを連続して作成および終了できることがわかりました。作成されたプロセスはすぐに終了します。約 70 プロセス/秒の速度が約 1 時間持続しました。

コードを次のように変更したとき

from multiprocessing import Process
import os
import time

def f_sleep():
    time.sleep(1)

if __name__ == '__main__':
    import datetime
    starttime = datetime.datetime.now()

    processes = []
    PROCESS_COUNT = 100
    for i in xrange(PROCESS_COUNT):
        p = Process(target=f_sleep)
        processes.append(p)
        p.start()
    for i in xrange(PROCESS_COUNT):
        processes[i].terminate()
    now = datetime.datetime.now()
    print "Started/stopped %d processes in %s seconds" % (len(processes), str(now-starttime))

PROCESS_COUNT にさまざまな値を試してみましたが、実際よりもはるかに優れたスケーリングを期待していました。PROCESS_COUNT のさまざまな値に対して、次の結果が得られました。

  • 20 プロセスが 0.72 秒で完了
  • 1.45秒で30プロセス完了
  • 50 プロセスが 3.68 秒で完了
  • 14秒で100プロセス完了
  • 200 プロセスが 43 秒で完了
  • 300 プロセスが 77 秒で完了
  • 111 秒で 400 プロセスを完了

これは私が期待したものではありません.ボトルネックに達するまで、並列プロセス数を合理的に線形にスケールアップできると思っていましたが、プロセス作成のボトルネックにすぐにぶつかっているようです. 私が実行した最初のコードに基づいて、プロセス作成のボトルネックにぶつかる前に、1 秒あたり 70 プロセス近くのプロセスを作成できると確信していました。

完全な仕様には触れませんが、ラップトップは完全にパッチが適用された Windows XP を実行し、4Gb の RAM を搭載し、それ以外はアイドル状態であり、かなり新しいものです。こんなに早くボトルネックになるとは思えません。

ここでコードに明らかに間違ったことをしていますか、それとも XP/Python の並列プロセスの作成は、12 か月前のラップトップでは本当に効率が悪いのでしょうか?

4

5 に答える 5

7

ええと、Windowsプロセス管理は実際にはうまく拡張できません。プロセスが多いほど、新しいプロセスをスケジューリングに挿入するのに時間がかかります。

ここで、これを他のOSカーネル、たとえばLinuxと比較します。Linuxでは、カーネル2.6.8(これが可能なスケジューラーが導入されたとき)以降、プロセスの作成は実質的にO(1)(定数時間)です。

ここではLinuxを販売しようとしているのではないことに注意してください。別のOSでプログラムを試して、自分の目で確かめることをお勧めします。

于 2012-06-22T07:23:13.177 に答える
3

さまざまなシナリオのプロファイリングとテストを行った結果、Windows では、一度に N 個のプロセスを生成して N 個すべてを強制終了し、N を再起動するよりも、単一のプロセスを生成して強制終了する方がはるかに高速であることがわかりました。

私の結論は、Windows は一度に 1 つのプロセスを非常に迅速に開始できるように十分なリソースを利用できるように維持していますが、かなりの遅延なしに 1 つ以上の新しい同時プロセスを開始するには十分ではありません。他の人が言っているように、Windows は新しいプロセスを開始するのが遅いですが、システム上で既に実行されている同時プロセスの数によって速度が半幾何学的に低下するようです - 単一のプロセスを開始するのは非常に高速ですが、複数のプロセスを開始するときあなたは問題を抱えています。これは、存在する CPU の数、マシンのビジー状態 (私のテストでは通常 5% 未満の CPU)、Windows が物理サーバーまたは仮想サーバーのどちらで実行されているか、使用可能な RAM の量 (最大 32Gb でテストした場合) に関係なく適用されます。 RAM、最大 24Gb の空き容量)、... - Windows OS の制限のようです。

于 2012-07-12T10:03:40.443 に答える
2

私の記憶が正しければ、Linux とは対照的に、Windows は多くのプロセスを迅速に開始するようには設計されていませんでした。それは設計者があなたがやろうと思っていたことではありません.Linuxでは、inetd最適化を保証するのに十分な一般的な操作モデルですが、プロセスの作成は地獄のように最適化されました.

于 2012-06-22T08:29:37.853 に答える
2

4Gb RAM を搭載した Ubuntu 11.04 Dell Precision でコードをテストしたところ、次の結果が得られました。

Started/stopped 100 processes in 0:00:00.051061 seconds
Started/stopped 150 processes in 0:00:00.094802 seconds
Started/stopped 200 processes in 0:00:00.153671 seconds
Started/stopped 300 processes in 0:00:00.351072 seconds
Started/stopped 400 processes in 0:00:00.651631 seconds
Started/stopped 470 processes in 0:00:01.009148 seconds
Started/stopped 1000 processes in 0:00:02.532036 seconds
Started/stopped 10000 processes in 0:00:29.677061 seconds

同じ数のプロセスで実行するたびに、少なくとも 10% の変動性がありました。これが役立つことを願っています。

于 2012-06-22T08:24:55.263 に答える
0

Linux では、多くの Python プロセスの作成にも問題があると主張したいと思います。p.start() を 500 回実行すると、非常に遅くなります。

時には、長期間機能する何千ものプロセスを作成する必要があります。

上記の例では、1 秒後に処理を終了し始めるため、1 分間に PROCESS_COUNT 個のプロセスがアクティブになっているわけではありません。そのため、上記の 2 秒で 1000 個のプロセスを作成した場合、半分以上のプロセスが作成手順の最後まで終了しました。

from multiprocessing import Process
def sample():
        sleep(13)
start = time()
for i in range(1500):
    p = Process(target=sample)
    p.daemon = True
    p.start()
 end = time()
 print end - start 

SUSE ENTERPRISEで140コアサーバーを試し、Ubuntuを搭載したラップトップで試しました-ダイナミクスは同じです(サーバーの結果):

500 processes start  - 1.36 s
1000 processes start - 9.7 s
1500 processes start - 18.4 s
2000 processes start - 24.3 s
3000 processes start - 43.3 s

フォークの前にこの呼び出しが原因です。新しい子プロセスごとに時間がかかります

def _cleanup():
    # check for processes which have finished
    for p in list(_current_process._children):
        if p._popen.poll() is not None:
            _current_process._children.discard(p)

私が覚えているように、プロセスに manager.Value があり、少し重い場合、RAM の 10 分の 1 GB が必要で、起動時間が少し長くなります。

于 2015-09-03T16:47:29.943 に答える