1. 程式人生 > >python並行程式設計 - 介紹篇

python並行程式設計 - 介紹篇

目錄1

介紹篇
執行緒篇
程序篇
非同步篇
GPU篇
分散式篇


設計並行程式設計

任務分解:將程式分解為任務,在不同處理器上執行以實現並行化。(可以使用以下兩種方法)

  • 領域分解:將問題資料分解 (當處理的資料量很大時,分開處理)
  • 功能性分解:將問題分解為任務 (把大的任務分解為多個小任務處理)

任務分配:將任務分配到各個處理器上 (目的是負載均衡

聚集:將小任務與大任務合併到一起從而改進效能的過程
如果任務數量遠遠超過可用的處理器數量,由於執行緒切換等其它因素會導致效率降低
如果計算機有針對大量小任務而進行特別的設計,如採用GPU計算,那將能從大量小任務的執行中獲益

對映:指定哪個任務將要執行 (目標是將總執行時間降到最低)(可以使用以下2中策略,這2個策略間由於是衝突的,需要做出權衡)

  • 通訊頻繁的任務放在同一個處理器中來增加區域性性
  • 可以併發執行的任務放在不同的處理器中增加併發性

注意! 對映問題,即NP完備2。對於相同大小的任務,很容易直接對映
如果是每個任務的工作量千差萬別,就需要採用負載均衡演算法在執行期間確定聚集與對映的策略。
如果在程式執行期間通訊量或任務量發生變化的情況,可以使用動態的負載均衡演算法

(不同的問題存在多種負載均衡演算法,有全域性或區域性的。全域性演算法需要全域性的掌握,會增加大量成本。區域性演算法只依賴於特定任務本身的資訊,不過難以找到最優)
(存在 管理者/執行者(管理者排程)、層次化的管理者/執行者(分組,每組都有個管理者排程)、去中心化的模型(每個處理器會維護自己的任務池))


程序與執行緒比較3

效能比較

多執行緒比多程序成本低,但效能更低

優缺點對比

多程序優點

  • 每個程序相互獨立,子程序異常不影響父程序
  • 通過增加CPU,就可容易擴充效能
  • 沒有鎖的影響
  • 每個子程序都有獨立的地址空間和資源

多程序缺點

  • 邏輯控制複雜,需要和主程序互動
  • 需要跨程序邊界,如有大量資料需要傳輸不太好,適合少量資料傳輸、密集運算

多執行緒優點

  • 邏輯控制簡單
  • 需跨程序邊界
  • 可直接共享資源
  • 資源消耗比程序

多執行緒缺點

  • 其中的某個執行緒崩潰可能會影響整個程式
  • 執行緒之間的同步和的控制比較麻煩
  • 每個執行緒與主執行緒共用地址空間

注意! 無論程序,還是執行緒多了以後,他們的排程也會消耗較多的CPU資源


python並行程式設計的問題

一般來說,一個程序可以包含多個並行執行緒。不過,Python直譯器並非完全是執行緒安全的。為了支援多執行緒的Python程式,會使用名為全域性直譯器鎖GIL(Global Interpreter Lock)的全域性鎖。這意味著在同一時刻只有一個執行緒會執行Python程式碼。(如果多個執行緒嘗試訪問同一個物件資料,那麼它可能處於不一致的狀態)

故此,python中的並行程式設計想要發揮多核的優勢推薦使用多程序代替多執行緒

為什麼不去除GIL? 更多細節:Python 最難的問題


python中程序與執行緒的效率

由於python自身存在GIL的問題,同一時刻只能執行一個執行緒,在一些實驗對比中,我們會發現python中程序與執行緒之間的差異,在這裡直接給出結論
對比操作:CPU密集型IO密集型網路請求密集型

多執行緒

  • CPU密集型操作,效能更差
  • IO密集型操作,效能更差
  • 網路請求密集型操作,優勢明顯

多程序

  • CPU密集型操作,優勢明顯
  • IO密集型操作,優勢明顯
  • 網路請求密集型操作,與多執行緒相差無幾,卻更佔用CPU等資源

故CPU密集型、IO密集型操作,首選多程序,網路請求密集型選擇多執行緒

(附:如果追求效率,CPU密集型操作應首選C/C++語言
IO密集型操作,CPU消耗很少,換用C/C++也很難得到效率的提升,應採用開發效率高的語言,指令碼語言是首選)

更多細節:Python中單執行緒、多執行緒和多程序的效率對比實驗



  1. 參考書籍:《Python並行程式設計手冊》 ↩︎

  2. NP完全問題是世界七大數學難題之一
    所有的完全多項式非確定性問題,都可以轉換為一類叫做滿足性問題的邏輯運算問題。既然這類問題的所有可能答案,都可以在多項式時間內計算,人們於是就猜想,是否這類問題存在一個確定性演算法,可以在多項式時間內直接算出或是搜尋出正確的答案呢?這就是著名的NP=P?的猜想(百度百科)
    https://zh.wikipedia.org/wiki/NP完全(wiki百科) ↩︎

  3. 參考:追溯到最早的一篇2011年的頁面已失效了 ↩︎