11

L > M の場合、L 個のコアを持つマシンで N 個の独立したタスクを正確に M 個のプロセッサに分散する方法を知りたいです。I/O を利用できるようにしたいので、すべてのプロセッサを使用したくありません。私が試した解決策は、すべてのプロセッサに分散され、システムが動かなくなったようです。

マルチプロセッシング モジュールが最適だと思います。

数値シミュレーションをしています。私のバックグラウンドはコンピュータ サイエンスではなく物理学なので、残念ながら、サーバー/クライアント、プロデューサー/コンシューマーなどの標準的なタスク モデルに関する議論を完全には理解していないことがよくあります。

私が試したいくつかの単純化されたモデルを次に示します。

シミュレーションを実行する関数run_sim(**kwargs)(以下を参照) と、シミュレーション用の kwargs の長いリストがあり、8 コアのマシンがあるとします。

from multiprocessing import Pool, Process

#using pool
p = Pool(4)
p.map(run_sim, kwargs)

# using process
number_of_live_jobs=0
all_jobs=[]
sim_index=0
while sim_index < len(kwargs)+1:
   number_of_live_jobs = len([1 for job in all_jobs if job.is_alive()])
   if number_of_live_jobs <= 4:
      p = Process(target=run_sim, args=[], kwargs=kwargs[sim_index])
      print "starting job", kwargs[sim_index]["data_file_name"]
      print "number of live jobs: ", number_of_live_jobs
      p.start()
      p.join()
      all_jobs.append(p)
      sim_index += 1

プロセッサの使用率を「top」、「1」の順で見ると、どちらの場合でもすべてのプロセッサが使用されているようです。「top」の出力を誤解しているのは論外ではありませんが、run_simulation()プロセッサを集中的に使用する場合、マシンはひどく動かなくなります。

仮説シミュレーションとデータ:

# simulation kwargs
numbers_of_steps = range(0,10000000, 1000000)
sigmas = [x for x in range(11)]
kwargs = []
for number_of_steps in numbers_of_steps:
   for sigma in sigmas:
      kwargs.append(
         dict(
            number_of_steps=number_of_steps,
            sigma=sigma,
            # why do I need to cast to int?
            data_file_name="walk_steps=%i_sigma=%i" % (number_of_steps, sigma),
            )
         )

import random, time
random.seed(time.time())

# simulation of random walk
def run_sim(kwargs):
   number_of_steps = kwargs["number_of_steps"]
   sigma = kwargs["sigma"]
   data_file_name = kwargs["data_file_name"]
   data_file = open(data_file_name+".dat", "w")
   current_position = 0
   print "running simulation", data_file_name
   for n in range(int(number_of_steps)+1):
      data_file.write("step number %i   position=%f\n" % (n, current_position))
      random_step = random.gauss(0,sigma)
      current_position += random_step

   data_file.close()
4

5 に答える 5

3

Linux を使用している場合は、プログラムを起動するときにタスクセットを使用します

fork(2) によって作成された子は、親の CPU アフィニティ マスクを継承します。アフィニティ マスクは、execve(2) 全体で保持されます。

TASKSET(1)
Linux ユーザーズマニュアル
TASKSET(1)

NAME タスクセット - プロセスの CPU アフィニティを取得または設定します

形式 taskset [オプション] mask コマンド [引数]... taskset [オプション] -p [マスク] pid

説明 taskset は、PID を指定して実行中のプロセスの CPU アフィニティを設定または取得するか、指定した CPU アフィニティで新しい COMMAND を起動するために使用されます。CPU アフィニティは、プロセスをシステム上の特定の CPU セットに「結合」するスケジューラ プロパティです。Linux スケジューラは指定された CPU アフィニティを尊重し、プロセスは他の CPU では実行されません。Linux スケジューラは、自然な CPU アフィニティもサポートしていることに注意してください。スケジューラは、パフォーマンス上の理由から、可能な限り同じ CPU でプロセスを維持しようとします。したがって、特定の CPU アフィニティを強制することは、特定のアプリケーションでのみ有効です。

CPU アフィニティはビットマスクとして表され、最下位ビットが最初の論理 CPU に対応し、最上位ビットが最後の論理 CPU に対応します。特定のシステムにすべての CPU が存在するわけではありませんが、マスクは存在するよりも多くの CPU を指定する場合があります。検索されたマスクは、システム上の物理的な CPU に対応するビットのみを反映します。無効なマスク (つまり、現在のシステムで有効な CPU に対応していないマスク) が指定された場合、エラーが返されます。通常、マスクは 16 進数で指定されます。

于 2009-10-15T21:50:24.453 に答える
2

次のパッケージを調べてみてください。

http://pypi.python.org/pypi/affinity

sched_setaffinity と sched_getaffinity を利用したパッケージです。

欠点は、非常に Linux 固有であることです。

于 2009-10-15T21:16:49.077 に答える
2

私のデュアルコアマシンでは、プロセスの総数が尊重されます。

p = Pool(1)

その後、常に 1 つの CPU しか使用されていません。プロセスは別のプロセッサに自由に移行できますが、別のプロセッサはアイドル状態になります。すべてのプロセッサが同時に使用されている可能性があるかどうかはわかりません。そのため、これが I/O の問題にどのように関連するかはわかりません。もちろん、シミュレーションが I/O バウンドの場合、コアの使用状況に関係なく I/O が遅くなります...

于 2009-10-15T22:06:38.820 に答える
1

pypar モジュールを使用してみてください。アフィニティを使用して特定のコアに CPU アフィニティを設定する方法がわかりません

于 2011-03-26T18:25:00.913 に答える
1

おそらくばかげた観察ですが、Python の経験がないことをお許しください。

しかし、完了したタスクの while ループ ポーリングはスリープ状態にならず、常に 1 つのコアを消費していますね。

もう 1 つの注意点は、タスクが I/O バウンドの場合、M を並列ディスク (?) の数に合わせて調整する必要があることです。それらが別のマシンに NFS マウントされている場合、M>L になる可能性があります。 .

運がいい!

于 2009-10-15T23:50:03.373 に答える