Last Updated on 2021-07-11 by Clay
Python 雖然是個熱門、簡單又優雅的程式語言,可是其執行的效能卻一直為其他程式語言的使用者所詬病。所以在像是『資料前處理』這方面,熟練地使用多執行緒、多行程就是一件非常重要的事情。
今天我要紀錄的就是 Python 當中 Pool 進程池的使用方法。在多核心的 CPU 當中,利用率經常比單純使用 Threading 來得高,也不會因為某一行程死掉而導致程式崩潰 —— 聽說在 Threading 當中會遇到這樣的狀況,不過我個人是沒有遇過。
值得注意的是,要小心多個行程之間存取同樣文件、變數的問題。如果情況允許,建議直接使用任務的回傳值來統一資料,以面發生資料缺少的問題。
基本的 Pool 使用方法
首先,multiprocessing 是 Python 原生的套件,並不需要額外安裝。另外,我們需要將我們要多行程處理的任務寫成 Function。
以下是個最簡易的範例程式:
# coding: utf-8 import multiprocessing as mp # Task def task(item): return item % 10 if __name__ == '__main__': pool = mp.Pool(processes=4) inputs = range(10) results = pool.map(task, inputs) print(results)
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
首先我們需要使用:
pool = mp.Pool(processes=4)
來建立進程池。其中 processes 代表著調用 CPU 核心數,如無設定,則預設使用系統全部核心。接著使用:
results = pool.map(task, inputs)
來處理任務。其中 inputs 是一個 Python 的可迭代對象,會把每一個迭代元素輸入進我們定義的 task() 函式中進行處理,並依照所設定 CPU 核心數平行處理任務,提昇任務效率。
而 results 則是所有任務完成之後的回傳值。
以上,就是一個最簡單的 Python Pool 程式。
多行程中顯示進度條
然而,若是我們的工作十分龐大,許多時候我們需要有一個進度條,好能隨時確認程式仍然正常運行。那麼,可以參考下方作法。
首先,推薦先安裝 Python 中讓迭代視覺化的套件 tqdm:
pip3 install tqdm
然後,將程式更改為:
# coding: utf-8 import multiprocessing as mp import tqdm # Task def task(item): return item % 10 if __name__ == '__main__': pool = mp.Pool(processes=4) inputs = range(10) results = [] for result in tqdm.tqdm(pool.imap_unordered(task, inputs), total=len(inputs)): results.append(result) print(results)
Output:
100%|████████████████████████████████████████████| 10/10 [00:00<00:00, 20877.57it/s]
[0, 1, 2, 4, 3, 5, 6, 7, 8, 9]
這樣一來,我們就能一邊享有多行程的高速處理、一邊又能清楚看見當前進度了。
References
- https://tutorialedge.net/python/python-multiprocessing-tutorial/
- https://stackoverflow.com/questions/5666576/show-the-progress-of-a-python-multiprocessing-pool-map-call
- https://bentyeh.github.io/2019/07/22/Python-multiprocessing-progress.html