ProcessPoolExecutorの動きが、Processと違ってあまり期待通りじゃないように見えたので、検証してみました。
executor.map()のresultをprint()してもあまりよくわからないので、time.sleep()を入れながらファイルを作成させて、ファイルができる順番やタイミングを観察してみました。
import time
from concurrent.futures import ProcessPoolExecutor
def f(args):
wait_seconds = args
time.sleep(wait_seconds)
try:
with open(f"{wait_seconds}.txt", "w") as file:
print(f"{wait_seconds}", file=file)
except FileNotFoundError as e:
pass
return wait_seconds
if __name__ == "__main__":
params = [
(1),
(7),
(2),
(3),
(4),
(5),
(6),
]
with ProcessPoolExecutor(max_workers=3) as executor:
[print(r) for r in executor.map(f, params, chunksize=3)]
結果
ファイルができた順番。
1.txt
3.txt
6.txt
4.txt
7.txt
2.txt
5.txt
executor.map()のパラメータ chunksize=3 により、paramsが3つずつの集団に仕分けされて、各集団ごとは逐次処理になるようです。
params = [
(1),
(7),
(2),
(3),
(4),
(5),
(6),
]
↓
グループ1:
(1)
(7)
(2)
グループ2:
(3)
(4)
(5)
グループ3:
(6)
なので、
1.txt <- グループ1の1番手
3.txt <- グループ2の1番手
6.txt <- グループ3の1番手(グループ3はこれで終わり)
4.txt <- グループ2の2番手
7.txt <- グループ1の2番手
2.txt <- グループ1の3番手
5.txt <- グループ2の3番手
となるようでした。
そういうのだったのか。
ちなみにchunksizeを上げるとオーバーヘッドがものすごく、128とかにすると起動に数分かかりました。
max_workersやCPU、処理の内容と綿密にご相談ですね。