我正在嘗試簡化一個程式,該程式涉及一組可以并行完成的短任務,在進入下一步之前必須比較這組任務的結果(這再次涉及一組短任務,然后另一組,等等)。由于這些任務的復雜程度,multiprocessing由于設定時間,不值得使用。我想知道是否有另一種比線性更快的并行執行這些短任務的方法。我可以在這個站點上找到的
uj5u.com熱心網友回復:
我的第一個觀察是,numbers只需將函式的運行時間定義為:
def numbers(a, b):
return range(a, b)
其次,numpy由于對全域解釋器鎖 (GIL) 的爭用,如果沒有 C 語言運行時庫(例如),這可以防止發生任何型別的并行化(并且asyncio只使用單個執行緒)。
第三,針對 100% CPU 任務運行純 Python 代碼實作性能改進的唯一方法是使用多處理。但是,在創建行程池時存在 CPU 開銷,在將引數從主行程傳遞到行程池中的行程運行所在的地址空間時存在 CPU 開銷,并在回傳結果時再次開銷。因此,對于任何性能改進,worker 函式linear_sum都不是微不足道的;它必須需要足夠的 CPU 處理才能保證我剛剛提到的額外開銷。
以下基準運行作業函式,重命名為compute_sum,現在接受 a 作為其引數range。為了進一步減少開銷,我引入了一個函式split,該函式將接受傳遞的range引數并生成多個range實體,從而無需使用numpy和生成陣列。基準計算使用單個執行緒(線性),多執行緒池和一個多處理池之和為運行兩次n = 2000和n = 50_000_000。基準測驗顯示所有行程的運行時間和總 CPU 時間。
對于n = 2000,正如預期的那樣,多處理的性能比線性和多執行緒都差。對于n = 50_000_000,由于額外的上述開銷,多處理的總 CPU 時間比線性和多執行緒的總時間略高。但是現在經過的時間已經明顯減少了。對于 的兩個值n,多執行緒都是失敗者。
from multiprocessing.pool import Pool, ThreadPool
import time
def split(iterable, n):
k, m = divmod(len(iterable), n)
return (iterable[i * k min(i, m):(i 1) * k min(i 1, m)] for i in range(n))
def compute_sum(r):
t = time.process_time()
return (sum(r), time.process_time() - t)
if __name__ == '__main__':
for n in (2000, 50_000_000):
r = range(0, n 1)
t1 = time.time()
s, cpu = compute_sum(r)
elapsed = time.time() - t1
print(f'n = {n}, linear elapsed time = {elapsed}, total cpu time = {cpu}, sum = {s}')
t1 = time.time()
t2 = time.process_time()
thread_pool = ThreadPool(4)
s = 0
for return_value, process_time in thread_pool.imap_unordered(compute_sum, split(r, 4)):
s = return_value
elapsed = time.time() - t1
cpu = time.process_time() - t2
print(f'n = {n}, thread pool elapsed time = {elapsed}, total cpu time = {cpu}, sum = {s}')
thread_pool.close()
thread_pool.join()
t1 = time.time()
t2 = time.process_time()
pool = Pool(4)
s = 0
cpu = 0
for return_value, process_time in pool.imap_unordered(compute_sum, split(r, 4)):
s = return_value
cpu = process_time
elapsed = time.time() - t1
cpu = time.process_time() - t2
print(f'n = {n}, multiprocessing elapsed time = {elapsed}, total cpu time = {cpu}, sum = {s}')
pool.close()
pool.join()
print()
印刷:
n = 2000, linear elapsed time = 0.0, total cpu time = 0.0, sum = 2001000
n = 2000, thread pool elapsed time = 0.00700068473815918, total cpu time = 0.015625, sum = 2001000
n = 2000, multiprocessing elapsed time = 0.13200139999389648, total cpu time = 0.015625, sum = 2001000
n = 50000000, linear elapsed time = 2.0311124324798584, total cpu time = 2.03125, sum = 1250000025000000
n = 50000000, thread pool elapsed time = 2.050999164581299, total cpu time = 2.046875, sum = 1250000025000000
n = 50000000, multiprocessing elapsed time = 0.7579991817474365, total cpu time = 2.359375, sum = 125000002500000
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/366706.html
