# Python 的 Multiprocessing 使用時機: 當你有N個檔案(N>100)要用for處理的時候,一個一個解不如用不同的process同步進行。 這麼做可以讓需要跑半天的code加速到吃個點心喝個咖啡回來就做完了 --- #### 此文假設讀者已對process 的概念有了解 在python裡面的multiprocessing.Pool 是一個像是task scheduler的東西,可以提供幾種類型的task distributing 的方法。 用法如以下的starmap(詳情見[淺談 Multi-processing pool 使用方法](https://www.maxlist.xyz/2020/03/20/multi-processing-pool/),此文介紹starmap是因為這個函數可以傳multiple argument),使用者需將你的task (Get_phonationdictbag_map)寫成function的形式,要做的就是將準備好的argument(file_block)丟進那個function。 multiprocessing.Pool 好處就在已經幫你實踐join和process的收放了,可安心的直接丟function ``` pool = Pool(int(os.cpu_count())) pool.starmap(Get_phonationdictbag_map, [([file_block]) for file_block in keys]) ``` Get_phonationdictbag_map 函數裡面可以print出當下process ID的資訊比較好掌握是否multiprocess有真的在跑, 至於 ``` def Get_phonationdictbag_map() print(" process PID", os.getpid(), " running") /// your code /// print("PID {} Getting ".format(os.getpid()), "Done") ``` 最後如果要回收每個process計算完的結果,可以用一個變數來接收回傳的值就好 `final_result = pool.starmap(Get_phonationdictbag_map, [([file_block]) for file_block in tqdm(keys)])` --- ### 補充: 由於process在開始與回收之間都會有overhead,所以建議用batch的方式讓一個process處理多一點檔案,並且設計讓一個長度為N的file list 切成總共有M個,每個數量有"interval"的batch,就可以節省時間。 ``` def Get_phonationdictbag_map(files) print(" process PID", os.getpid(), " running") for file in files: /// your code /// print("PID {} Getting ".format(os.getpid()), "Done") interval=20 keys=[] for i in range(0,len(files),interval): # print(list(combs_tup.keys())[i:i+interval]) keys.append(files[i:i+interval]) flat_keys=[item for sublist in keys for item in sublist] assert len(flat_keys) == len(files) final_result = pool.starmap(Get_phonationdictbag_map, [([file_block]) for file_block in tqdm(keys)]) ``` --- ## 總結 如果要將程式改為multiprocess,會要拆成下列步驟: 1. 定義你要做的task (task之間的I/O盡量不要有依賴性) 2. 用pool.starmap(func,iterable) 來將參數丟進func a. ## 這邊的iterabler最簡單的可以用一個list就好了 3. final_result 會是一個list裡面每個element存每個process return出來的結果 #### 補充2 好像很好用的multi-processing的package [Ray](https://github.com/ray-project/ray) ###### tags: `Multiprocessing`