私は、終了するのにかなり長い時間がかかる(かなり大きな)プログラムを作成し、プログラムを高速化する方法を検討し始めました。
プログラムの実行中にタスクマネージャを開くと、1つのコアしか使用されていないことがわかりました。
いくつかの調査の後、私はこのウェブサイトを見つけました: numpyをインポートした後、マルチプロセッシングが単一コアのみを使用するのはなぜですか?os.system("taskset -p 0xff %d" % os.getpid())
のソリューションを提供しますが、これは私にとっては機能しません、そして私のプログラムはシングルコアで動作し続けます。
次にこれを見つけました: is python複数のコアで実行できますか? 、これはマルチプロセッシングの使用を指しています。
したがって、マルチプロセッシングを調べた後、それを使用する方法についてこのドキュメンタリーに遭遇しました https://docs.python.org/3/library/multiprocessing.html#examples
私はコードを試しました:
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob',))
p.start()
p.join()
a = input("Finished")
(IDLEではなく)コードを実行した後、次のように述べられています。
Finished
hello bob
Finished
注:最初にEnterキーを押したときに「完了」と表示された後
この後、私はさらに混乱し、2つの質問があります
最初:それはまだ複数のコアで動作しません(私は8コアIntel i7を持っています)
2番目:ifステートメントコードを実行する前に「Finished」と入力するのはなぜですか(まだ終了していないのです!)
2番目の質問に最初に答えるには、a = input("Finished")
がif __name__ == '__main__':
コードブロックの外にあるため、「終了」がターミナルに出力されます。したがって、これはモジュールが最初に読み込まれたときに割り当てられ、モジュール内のコードが実行される前に実行されるモジュールレベルの定数です。
最初の質問に答えるために、実行するプロセスを1つだけ作成し、続行する前に完了するまで待機しました。これにより、マルチプロセッシングの利点がなくなり、新しいプロセスを作成するオーバーヘッドが発生します。
複数のプロセスを作成するため、ある種のコレクション(pythonリストなど)を介してプールを作成し、すべてのプロセスを開始する必要があります。
実際には、プロセッサの数よりも多くを考慮する必要があります(使用可能なメモリの量、クラッシュしたワーカーを再起動する機能など)。ただし、これは上記のタスクを完了する簡単な例です。
import datetime as dt
from multiprocessing import Process, current_process
import sys
def f(name):
print('{}: hello {} from {}'.format(
dt.datetime.now(), name, current_process().name))
sys.stdout.flush()
if __name__ == '__main__':
worker_count = 8
worker_pool = []
for _ in range(worker_count):
p = Process(target=f, args=('bob',))
p.start()
worker_pool.append(p)
for p in worker_pool:
p.join() # Wait for all of the workers to finish.
# Allow time to view results before program terminates.
a = input("Finished") # raw_input(...) in Python 2.
また、ワーカーを開始した直後に参加した場合、各ワーカーがタスクを完了するのを待ってから、次のワーカーを開始することにも注意してください。タスクの順序が連続的でなければならない場合を除き、これは一般的に望ましくありません。
通常は間違っています
worker_1.start()
worker_1.join()
worker_2.start() # Must wait for worker_1 to complete before starting worker_2.
worker_2.join()
通常望ましい
worker_1.start()
worker_2.start() # Start all workers.
worker_1.join()
worker_2.join() # Wait for all workers to finish.
詳細については、次のリンクを参照してください。