[英]Concurrency/Parallelism on Windows with Python
我開發了簡單的程序來解決八個皇后問題。 現在我想用不同的元參數做更多的測試,所以我想快速完成。 我經歷了幾次分析迭代,並且能夠顯着減少運行時間,但我達到了我認為只有部分計算同時可以使它更快的程度。 我嘗試使用multiprocessing
和concurrent.futures
模塊,但它並沒有大大改善運行時間,在某些情況下甚至減慢了執行速度。 那只是給出一些背景。
我能夠提出類似的代碼結構,其中順序版本節拍並發。
import numpy as np
import concurrent.futures
import math
import time
import multiprocessing
def is_prime(n):
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True
def generate_data(seed):
np.random.seed(seed)
numbers = []
for _ in range(5000):
nbr = np.random.randint(50000, 100000)
numbers.append(nbr)
return numbers
def run_test_concurrent(numbers):
print("Concurrent test")
start_tm = time.time()
chunk = len(numbers)//3
primes = None
with concurrent.futures.ProcessPoolExecutor(max_workers=3) as pool:
primes = list(pool.map(is_prime, numbers, chunksize=chunk))
print("Time: {:.6f}".format(time.time() - start_tm))
print("Number of primes: {}\n".format(np.sum(primes)))
def run_test_sequential(numbers):
print("Sequential test")
start_tm = time.time()
primes = [is_prime(nbr) for nbr in numbers]
print("Time: {:.6f}".format(time.time() - start_tm))
print("Number of primes: {}\n".format(np.sum(primes)))
def run_test_multiprocessing(numbers):
print("Multiprocessing test")
start_tm = time.time()
chunk = len(numbers)//3
primes = None
with multiprocessing.Pool(processes=3) as pool:
primes = list(pool.map(is_prime, numbers, chunksize=chunk))
print("Time: {:.6f}".format(time.time() - start_tm))
print("Number of primes: {}\n".format(np.sum(primes)))
def main():
nbr_trails = 5
for trail in range(nbr_trails):
numbers = generate_data(trail*10)
run_test_concurrent(numbers)
run_test_sequential(numbers)
run_test_multiprocessing(numbers)
print("--\n")
if __name__ == '__main__':
main()
當我在我的機器上運行它 - Windows 7,帶有四個核心的英特爾酷睿i5時,我得到了以下輸出:
Concurrent test
Time: 2.006006
Number of primes: 431
Sequential test
Time: 0.010000
Number of primes: 431
Multiprocessing test
Time: 1.412003
Number of primes: 431
--
Concurrent test
Time: 1.302003
Number of primes: 447
Sequential test
Time: 0.010000
Number of primes: 447
Multiprocessing test
Time: 1.252003
Number of primes: 447
--
Concurrent test
Time: 1.280002
Number of primes: 446
Sequential test
Time: 0.010000
Number of primes: 446
Multiprocessing test
Time: 1.250002
Number of primes: 446
--
Concurrent test
Time: 1.260002
Number of primes: 446
Sequential test
Time: 0.010000
Number of primes: 446
Multiprocessing test
Time: 1.250002
Number of primes: 446
--
Concurrent test
Time: 1.282003
Number of primes: 473
Sequential test
Time: 0.010000
Number of primes: 473
Multiprocessing test
Time: 1.260002
Number of primes: 473
--
我有現在的問題是我是否可以通過同時運行在Windows上獲得某種更快Python 3.6.4 |Anaconda, Inc.|
。 我在這里閱讀SO( 為什么在Windows上創建比Linux更昂貴的新流程? ),在Windows上創建新流程的成本很高。 有什么辦法可以加快速度嗎? 我錯過了一些明顯的東西嗎
我也嘗試過只創建一次Pool
,但似乎沒什么幫助。
編輯:
原始代碼結構看起來或多或少像:
我的代碼結構或多或少像這樣:
class Foo(object):
def g() -> int:
# function performing simple calculations
# single function call is fast (~500 ms)
pass
def run(self):
nbr_processes = multiprocessing.cpu_count() - 1
with multiprocessing.Pool(processes=nbr_processes) as pool:
foos = get_initial_foos()
solution_found = False
while not solution_found:
# one iteration
chunk = len(foos)//nbr_processes
vals = list(pool.map(Foo.g, foos, chunksize=chunk))
foos = modify_foos()
與foos
有1000
元素。 不可能事先告訴算法收斂的速度和執行的迭代次數,可能是數千次。
UNIX變體下的進程更輕量級。 Windows進程很繁重,需要更多時間才能啟動。 線程是在Windows上進行多處理的推薦方法。 您也可以關注此主題: 為什么在Windows上創建比Linux更昂貴的新流程?
您的設置對多處理來說並不公平。 你甚至包括不必要的primes = None
分配。 ;)
一些要點:
數據大小
您生成的數據可以用於獲取流程創建的開銷。 嘗試使用range(1_000_000)
而不是range(5000)
。 在Linux上將multiprocessing.start_method
設置為'spawn'(在Windows上為默認值),這將繪制不同的圖片:
Concurrent test
Time: 0.957883
Number of primes: 89479
Sequential test
Time: 1.235785
Number of primes: 89479
Multiprocessing test
Time: 0.714775
Number of primes: 89479
重新使用你的游泳池
只要在程序中留下要稍后並行化的代碼,就不要離開池的with-block。 如果您在開始時僅創建一次池,則根本不包括將池創建到基准測試中。
NumPy的
Numpy部分能夠發布全局解釋器鎖( GIL )。 這意味着,您可以從多核並行性中受益,而無需創建進程的開銷。 無論如何,如果你正在做數學,盡量使用numpy。 嘗試使用numpy的concurrent.futures.ThreadPoolExecutor
和multiprocessing.dummy.Pool
代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.