python同時プログラミング-マルチスレッド同期非同期処理

2272 ワード

pythonマルチプロセスの学習時に、プロセス上で実行されるメソッドが複数のパラメータと複数の結果を受信する際に問題が発生しました.ここで学習を経てまとめます.
Pool.map()マルチパラメータタスクは、mapメソッドに複数のパラメータを転送するメソッドでは、以下のように予想される効果を達成できません.
def job(x ,y):
	return x * y

if __name__ == "__main__":
	pool = multiprocessing.Pool()
	res = pool.map(job, 2, 3)
	print res

したがって、複数のパラメータを持つメソッドをカプセル化するしかなく、プロセスでカプセル化を実行したメソッドは次のようになります.
def job(x ,y):
	return x * y


def job1(z):
    return job(z[0], z[1])


if __name__ == "__main__":
	pool = multiprocessing.Pool()
	res = pool.map(job1, [(2, 3), (3, 4)])
	print res

これにより、複数のパラメータを渡す効果psが得られます.複数の結果を得る必要がある場合は、複数のメタグループを1つのリストに転送できます.
Pool.apply_async()はapply_を使用して複数の反復結果を出力するasync()メソッドが複数のパラメータを受信するメソッドの場合、タスクメソッドで通常複数のパラメータを定義し、パラメータはメタグループ形式で入力すればよいがapply_async()メソッドは、複数の値を入力して複数の反復結果を取得すると、1つの値しか受信できないため、次のようにリスト生成式にメソッドを入れることができます.
def job(x):
    return x * x


if __name__ == "__main__":
    pool multiprocessing.Pool()
    res = [pool.apply_async(target=job, (i,)) for i in range(3)]
    print [r.get() for r in res]

1つのタスクの実行効率を向上させるには、タスクを分割し、このタスクを複数のサブタスクに分割し、マルチプロセスを利用して非同期実行、すなわち同時に処理することで、全体のタスク時間を短縮することができます.pythonのmultiprocessingパッケージには、非同期で実行できるプロセスタスクメソッドが2つあります.apply_async()とmap_async()は、両方ともタスクを追加し、マルチプロセスで同時に実行できます.しかし両者には重要な違いがあり、以下に説明する.
apply_の場合async(func,args),funcはタスクを実行する関数名,argsはリストまたはメタグループのような反復可能なオブジェクトであり,funcに渡すパラメータが含まれており,複数のサブタスクに対してapply_をそれぞれ複数回呼び出す.async()は1つずつ追加されますが、これはリスト解析によって実現され、複数のプロセスの結果が1つのリストに保存されます.map_についてはasync(func,iterable,chunksize)は、複数のサブタスクが同じ関数で実行される場合、パラメータが異なるだけで、分割されたパラメータをリスト形式でiterableを介して転送し、chunksizeパラメータを介してプロセス数を指定することができる(実際にはここのchunksize表はiterableの分割数を示しているが、プロセス数に等しくすることが望ましい).これでいちいち追加する必要はありません.
以上は両者のわずかな違いにすぎず、さらに重要な違いはapply_を通過すればasync()メソッドは、プロセスを手動で指定してタスクを追加するため、各プロセスの実行結果が独立して保存されます.このような利点は、いくつかのプロセスにエラーが発生し、異常が放出される可能性がありますが、他のプロセスも失敗することはありません.他のプロセスは影響を受けません.また、この異常を投げ出したプロセスの結果を取得すると、異常情報も返されます.でもmap_ならasync()メソッドは、サブパラメータタスクが独立しているわけではありません.サブパラメータタスクが例外を投げ出すと、他のサブパラメータタスクが停止します.つまり、独立したスレッドで異なるサブパラメータタスクを実行するわけではありません.
以上の比較から,タスクの分割により実行効率が向上すると,リスト解析によりapply_を用いることが分かる.async()メソッドはサブタスクを追加し、独立したマルチプロセスを使用してmap_より実行します.async()メソッドの方が良いので、この場合apply_async()が最適です.