在Python中用concurrent.futures建立執行緒池程序池

倒地發表於2024-04-05

簡介

Python3.2 帶來了 concurrent.futures 模組,藉此能夠快速使用執行緒池和程序池。

對於不需要控制優先順序與資源分配的多工,使用 concurrent.futures 模組快捷優雅。

示例程式碼與效果

import concurrent.futures
import time

def a_task(x):
    """模擬一個耗時的任務"""
    def  count(number) :
        for i in range(0, 10000000):
                i=i+1
        return i * number
    result_item = count(x)
    return result_item

number_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

if __name__ == "__main__":
    # 順序執行
    start_time = time.time()
    for item in number_list:
        print(a_task(item))
    print("Sequential execution in " + str(time.time() - start_time), "seconds")

    # 執行緒池執行
    start_time_1 = time.time()
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        futures = [executor.submit(a_task, item) for item in number_list]
        for future in concurrent.futures.as_completed(futures):
            print(future.result())
    print ("Thread pool execution in " + str(time.time() - start_time_1), "seconds")
    
    # 程序池
    start_time_2 = time.time()
    with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
        futures = [executor.submit(a_task, item) for item in number_list]
        for future in concurrent.futures.as_completed(futures):
            print(future.result())
    print ("Process pool execution in " + str(time.time() - start_time_2), "seconds")

執行後可以檢視各種方案的耗時。ThreadPoolExecutor 比直接執行快一些。ProcessPoolExecutor 可以不受 GIL 限制,極大縮短執行時間。

使用執行緒池和程序池

以程序池為例。

要開始使用進行池,首先需要建立一個 executor,用於存放與管理任務。

with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:

這裡可以用 max_workers 指定並行執行數量,預設為 CPU 核心數。

使用 .submit() 將任務送入到 executor 池中。.submit() 會返回一個 future 物件,這代表已經放入池中的、待完成的任務。

future = executor.submit(some_func, param1, param2)

現在就能夠用 .result() 讓這一個 future 執行,並獲取結果。與直接呼叫 some_func 不同,這是在程序池裡執行的。

result = future.result()

若現在手頭有一大堆的 future,那就使用 concurrent.future.as_completed() 全部執行。這會讓 executor 參與多程序排程,同時執行多個 future。

for future in concurrent.futures.as_completed(futures):
    print(future.result())

參考來源

  • 深度學習可好玩了​,“python併發程式設計入門:(四)concurrent.futures”,https://zhuanlan.zhihu.com/p/438627177
  • “2. 使用Python的 concurrent.futures 模組”,https://python-parallel-programmning-cookbook.readthedocs.io/zh-cn/latest/chapter4/02_Using_the_concurrent.futures_Python_modules.html

相關文章