Python3のマルチプロセスPoolのメソッドが沢山あってどれを使えばいいのか分からなかったので調べました。
#map関数
map関数は全ての結果が出るまでブロックします。
コードを実行してみると
map.py
from multiprocessing import Pool
from time import sleep
import time
start = time.time()
def do(waitTime):
print("do waitTime:{} 開始から{}秒経過".format(waitTime,time.time() - start))
sleep(waitTime)
return waitTime
if __name__ == '__main__':
waitTimes = [3,2,1]
with Pool(10) as p:
for result in p.map(do,waitTimes):
print("result waitTime:{} 開始から{}秒経過".format(result,time.time() - start))
結果は
do waitTime:3 開始から0.03541707992553711秒経過
do waitTime:2 開始から0.03555130958557129秒経過
do waitTime:1 開始から0.03568387031555176秒経過
result waitTime:3 開始から3.0372514724731445秒経過
result waitTime:2 開始から3.0373241901397705秒経過
result waitTime:1 開始から3.037338972091675秒経過
for result in p.map(do,waitTimes):
行の戻り値はlist型ですべてのプロセスが終了するまでfor文は実行されません
#imap関数
imap関数はmap関数の遅延評価版です。imap関数の戻り値はイテレータを返します。戻り値が確定したプロセスがあれば他のプロセスの完了を待たずにfor文を実行できます。しかし、渡した順番と同じ順番で返さなければならない制約があるために最初のプロセスが終了しなければ、他の処理が終了していてもいつまでたってもfor文が実行されません。
imap.py
from multiprocessing import Pool
from time import sleep
import time
start = time.time()
def do(waitTime):
print("do waitTime:{} 開始から{}秒経過".format(waitTime,time.time() - start))
sleep(waitTime)
return waitTime
if __name__ == '__main__':
waitTimes = [3,2,1]
with Pool(10) as p:
for result in p.imap(do,waitTimes):
print("result waitTime:{} 開始から{}秒経過".format(result,time.time() - start))
do waitTime:3 開始から0.03740239143371582秒経過
do waitTime:2 開始から0.03748369216918945秒経過
do waitTime:1 開始から0.0376131534576416秒経過
result waitTime:3 開始から3.041029930114746秒経過
result waitTime:2 開始から3.041118621826172秒経過
result waitTime:1 開始から3.0411417484283447秒経過
#imap_unordered関数
イテレーターが返す結果の順番が任意の順番で良いと見なされることを除けば imap() と同じです。
imap.py
from multiprocessing import Pool
from time import sleep
import time
start = time.time()
def do(waitTime):
print("do waitTime:{} 開始から{}秒経過".format(waitTime,time.time() - start))
sleep(waitTime)
return waitTime
if __name__ == '__main__':
waitTimes = [3,2,1]
with Pool(10) as p:
for result in p.imap_unordered(do,waitTimes):
print("result waitTime:{} 開始から{}秒経過".format(result,time.time() - start))
do waitTime:3 開始から0.03511857986450195秒経過
do waitTime:2 開始から0.035273075103759766秒経過
do waitTime:1 開始から0.035429954528808594秒経過
result waitTime:1 開始から1.0369133949279785秒経過
result waitTime:2 開始から2.0377516746520996秒経過
result waitTime:3 開始から3.038750171661377秒経過
おおうっ!処理が完了したプロセスがあれば他の処理を待たずに実行されています!
#まとめ
Python3のマルチプロセスPoolのメソッドはimap_unorderedを使うべし