AI實踐:如何應用多進程Multiprocessing編程?

multiprocessing和threading:

多線程 threading:計算機同一時間還是隻能處理一個線程

多核 multiprocessing:現在計算機都有多核處理器,將任務分給多個核來處理,他們有單獨的運算空間和計算能力,避免了多線程的劣勢。

導入包:

定義一個被線程和進程調用的函數

創建進程和線程

Queue功能:

Queue的功能是將每個核或線程的運算結果放在隊裏中, 等到每個線程或核運行完畢後再從隊列中取出結果, 繼續加載運算。原因很簡單, 多線程調用的函數不能有返回值, 所以使用Queue存儲多個線程運算的結果

定義一個被多線程調用的函數,q就像一個隊列,用來保存每次函數運行的結果

主函數:

效率比較:多線程、多進程、普通的消耗時間;

實際時間對比:

運行時間是 多進程 < 普通 < 多線程

進程池就是我們將所要運行的東西,放到池子裏,Python會自行解決多進程的問題。

導入包並定義函數:

有了池子之後,就可以讓池子對應某一個函數,向池子裏輸入數據,池子就會返回函數返回的值。

Pool和之前的Process的不同點是丟向Pool的函數有返回值,而Process的沒有返回值。

接下來用map()獲取結果,在map()中需要放入函數和需要迭代運算的值,然後它會自動分配給CPU所有核,返回結果。

除了map()函數,Pool還有apply_async()函數可以返回結果。apply_async()中只能傳遞一個值,只會放入一個核進行運算,傳入值時要注意是可迭代的,所以在傳入值後需要加逗號。

如何用apply_async()輸出多個迭代呢?多傳入幾個值試試~

合併代碼:

可以看出在apply用迭代器的得到的結果和用map得到的結果是一樣的

總結

1. Pool默認調用是CPU的核數,傳入processes參數可自定義CPU核數

2. map() 放入迭代參數,返回多個結果

3. apply_async()只能放入一組參數,並返回一個結果,如果想得到map()的效果需要通過迭代。

只有用共享內存才能讓CPU之間有交流。

Shared Value:(多線程中global value)

多進程,即使傳入global 變量,多進程中也無法交流,我們可以通過使用Value數據存儲在一個共享的內存表中。

Shared Array:(僅僅是一個一維列表)

這裏的Array和numpy中的不同,它只能是一維的,不能是多維的。

同樣和Value 一樣,需要定義數據形式,否則會報錯。

參考數據形式

各參數代表的數據類型

進程鎖的運用:使進程之間不會互相干擾

不加進程鎖

在上面的代碼中,我們定義了一個共享變量v,兩個進程都可以對它進行操作。 在job()中我們想讓v每隔0.1秒輸出一次累加num的結果,但是在兩個進程p1和p2 中設定了不同的累加值。所以接下來讓我們來看下這兩個進程是否會出現衝突。

運行一下:

145891213161720

我們可以看到,進程1和進程2在相互搶着使用共享內存v。

加進程鎖

爲了解決上述不同進程搶共享資源的問題,我們可以用加進程鎖來解決。

首先需要定義一個進程鎖

然後將進程鎖的信息傳入各個進程中

在job()中設置進程鎖的使用,保證運行時一個進程的對鎖內內容的獨佔

完整代碼:

運行一下,讓我們看看是否還會出現搶佔資源的情況:

12345811141720

顯然,進程鎖保證了進程p1的完整運行,然後才進行了進程p2的運行

參考自:莫煩python https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章