當有多個非相關任務需要處理時,並行能大大提高處理速度。這裡簡要介紹python的multiprocessing模組。
簡單多程序編寫
當我們任務數量確定而且比較少的時候,可以手動為每個任務指定乙個程序來執行。
import multiprocessing as mp
def f(a):
print(a)
if __name__ == '__main__':
# 這裡有三個任務,手動指定3個程序
p1 = mp.process(target=f, args=(1,))
p2 = mp.process(target=f, args=(2,))
p3 = mp.process(target=f, args=(3,))
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
# 輸出
使用程序池來處理多工
當我們任務比較多而且不確定數量(又或者想使得**更簡潔)的時候可以使用程序池pool來編寫多程序。
import multiprocessing as mp
def f(a):
return a
if __name__ == '__main__':
pool = mp.pool()
res = pool.map(f, (1, 2, 3, 4))
print(res)
# 輸出
[1, 2, 3, 4]
可以看到,程序池不僅可以方便的處理多程序,還將各個程序的的處理結果儲存了在乙個列表中。pool預設使用計算機所有cpu核來進行運算,也可使用pool(process=4)來指定並行的程序數。
import multiprocessing as mp
def f(a):
return a
if __name__ == '__main__':
pool = mp.pool()
print([r.get() for r in res])
# 輸出
[0, 1, 2, 3]
多引數函式的多程序
上面處理任務的函式都只有乙個引數,在實際情況這種情況是很少的,一般我們的函式都需要傳入多個引數。python2中未能支援傳多個引數,python3.3後則有starmap來支援傳入多引數。
import multiprocessing as mp
def f(a, b):
return (a, b)
if __name__ == '__main__':
pool = mp.pool()
res = pool.starmap(f, ((1, 2), ('a', 'b')))
print(res)
# 輸出
[(1, 2), ('a', 'b')]
另乙個傳多個引數的方法是通過python中的魔術方法*args:
import multiprocessing as mp
def f(*l):
a, b = l[0] # 為什麼這裡是l[0]而不是l?因為這裡傳入的l是乙個巢狀元組((a,b),)。
return (a, b)
if __name__ == '__main__':
pool = mp.pool()
res = pool.map(f, ((1, 2), ('a', 'b')))
print(res)
# 輸出
[(1, 2), ('a', 'b')]
亦或使用**kwargs:
import multiprocessing as mp
def f(*l):
d = l[0] # 這裡l為(,)
return (d['a'], d['b'])
if __name__ == '__main__':
pool = mp.pool()
res = pool.map(f, (, ))
print(res)
# 輸出
[(1, 2), (3, 4)]
共享記憶體和程序鎖
一般情況下,各個程序中的資料變數是無法發生交流的,但我們可以通過使用value資料儲存在乙個共享的記憶體表中。
import multiprocessing as mp
import time
def job(v, num):
for _ in range(5):
time.sleep(0.1) # 暫停0.1秒,讓輸出效果更明顯
v.value += num # v.value獲取共享變數值
print(v.value)
def multicore():
v = mp.value('i', 0) # 定義共享變數
p1 = mp.process(target=job, args=(v, 1))
p2 = mp.process(target=job, args=(v, 3)) # 設定不同的number看如何搶奪記憶體
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == '__main__':
multicore()
# 輸出
在上面的**中,我們定義了乙個共享變數v,兩個程序都可以對它進行操作。 在job()中我們想讓v每隔0.1秒輸出一次累加num的結果,但是在兩個程序p1和p2 中設定了不同的累加值。很明顯可以看到他們發生了衝突。
為了解決上述不同程序搶共享資源的問題,我們可以用加程序鎖來解決。
import multiprocessing as mp
def job(v, num, l):
l.acquire() # 鎖住
for _ in range(5):
time.sleep(0.1)
v.value += num # 獲取共享記憶體
print(v.value)
l.release() # 釋放
def multicore():
l = mp.lock() # 定義乙個程序鎖
v = mp.value('i', 0) # 定義共享記憶體
p1 = mp.process(target=job, args=(v, 1, l)) # 需要將lock傳入
p2 = mp.process(target=job, args=(v, 3, l))
p1.start()
p2.start()
p1.join()
p2.join()
if __name__ == '__main__':
multicore()
# 輸出
需要主義的是上面可能仍然會發生衝突——p1先執行還是p2先執行的問題。為了解決這個問題我們可以在start,join中決定他們的順序。
import multiprocessing as mp
def job(v, num, l):
l.acquire() # 鎖住
for _ in range(5):
time.sleep(0.1)
v.value += num # 獲取共享記憶體
print(v.value)
l.release() # 釋放
def multicore():
l = mp.lock() # 定義乙個程序鎖
v = mp.value('i', 0) # 定義共享記憶體
p1 = mp.process(target=job, args=(v, 1, l)) # 需要將lock傳入
p2 = mp.process(target=job, args=(v, 3, l))
p1.start()
p1.join()
p2.start()
p2.join()
if __name__ == '__main__':
multicore()
# 輸出
python多程序 Python多程序實踐
建立程序方式如下 可以通過lock鎖機制實現共享鎖,但比較常用的方式還是以上這些方式,效率更高,更安全。使用方式 構造 類方法 使用方式 構造 更多型別支援一般使用manager,支援的型別包括list,dict,namespace,lock,rlock,semaphore,boundedsemap...
python多程序 Python多程序程式設計詳解
本文 在 python 3.6 環境下測試通過。多程序 multiprocessing 模組是在 python 2.6 版本中加入的,和多執行緒 threading 模組類似,都是用來做並行運算的。不過python既然有了threading,為什麼還要搞乙個multiprocessing呢?這是因為...
python多程序優化 Python 多程序處理
嘗試學習python的多程序模組,對比多執行緒,大概的區別在 1.多程序的處理速度更快 2.多程序的各個子程序之間交換資料很不方便 多程序呼叫方式 程序基本使用multicore 程序池優化程序的呼叫multicore pool 在使用程序池的時候,運許函式有return,而基本用法中程序是接收不了...