# 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`