像鳥一樣思考更好的並行程式設計

認真期待發表於2018-05-15

介紹

編寫一個應用程式並行執行很困難,對吧?我的意思是,它一定很難,否則我們會看到各處的並行程式。我們所看到的都是平滑的並行應用程式,可以毫不費力地使用每個可用的核心。相反,多執行緒應用程式是例外而不是規則。

編寫並行程式似乎有兩個主要障礙:

  • 學習您選擇的語言提供的並行程式設計結構和/或約定

  • 視覺化您的並行程式的功能

第一項似乎很明顯:休息一下,學習所選程式語言的並行功能,然後離開你 - 並行程式將從你的編譯器中跳出。除非那天下午通常會變成幾天,這通常會變成一段更長的時間,而你選擇的語言的平行特徵的含義,併發症和後果則會被馴服。

第二項似乎應該提到幾乎是微不足道的。畢竟,開發一個新計劃的第一步是想象它的主要組成部分以及它們將如何運作。除了我們通常將我們的新程式視覺化為順序程式碼元件,以便我們稍後(如果必須的話)將某些並行的東西“栓上”。正是這種思維框架使我們從一開始就走上了錯誤的道路。

相反,我們需要考慮像鳥這樣的程式。或者說,成群的鳥兒。

背景

Avian計算專案是通過改進我們對並行程式設計的思考來改善並行程式設計的一種方式。Avian Computing鼓勵我們將並行程式視覺化為一群鳥,每個鳥(執行緒)獨立並非同步地執行操作,但它們同時作為一群來完成程式的目標。

我們都熟悉鳥類:它們被孵化出來,四處飛翔尋找食物,產卵並孵化自己的鳥類,然後死亡。Avian Computing將這些基本的鳥類行為轉化為開發人員可以利用的編碼框架來快速開發工作並行程式的原型。從構建這個工作原型獲得的知識深度和見解可以簡化最終軟體產品的開發。

Avian計算的實現

併發資源管理器(ConcX)是用Java編寫的Avian Computing的概念的免費開源實現。ConcX為使用者提供了一個可以建立和配置新鳥的GUI螢幕。配置完成後,可以啟動小鳥並在進度條上監控其活動。配置好的鳥群可以儲存為一個“群”,可以根據需要重新載入和執行。

像鳥一樣思考更好的並行程式設計

一旦孵化(開始),每隻鳥(線)遵循標準生命週期; 它尋找食物,消化找到的任何匹配的食物,儲存任何產生的食物,然後小睡一會兒。在配置的耐力時限內找不到食物的鳥類將因飢餓而死亡。活得太久的鳥會死於老年。成功吃足以滿足可配置設定的鳥類將複製(重複自己)。這個標準生命週期允許使用簡單自然的詞彙來處理執行緒管理的複雜性,這些詞彙幾乎可以直觀地理解。

ConcX依賴於Linda協調語言來從共享虛擬關聯儲存器(稱為元組空間)中放置和檢索物件。Linda起源於1986年,由Sudhir Ahuja,David Gelernter和Nicholas Carriero創作。Linda是幾個主要產品的基礎,包括Sun的JavaSpaces,IBM的TSpaces等等。

ConcX使用稱為TupleTree的Linda元組空間的簡化版本。鳥類通常配置為在TupleTree中食用和儲存食物豆莢。例如,RedPod可以被配置為吃RedPods的任何鳥食用,並且將被所有其他鳥類忽略。在消化它的食物莢後,一隻鳥會將加工後的物體存放回TupleTree,通常作為不同種類的食物莢(例如BluePod),以供不同的鳥類食用。

Linda(及其派生,TupleTree)提供了一個安全,簡單和強大的訊息傳遞機制。在ConcX中,TupleTree允許在使用者編寫的程式碼中沒有任何特殊的程式碼或注意事項的情況下共享物件,因為TupleTree同步(鎖定或以其他方式提供獨佔訪問)所有與其底層資料儲存互動的方法。

使TupleTree對所有鎖定負責,確保鳥兒接收的任何食物吊艙(物體)完全由該鳥類擁有,而不會使用鎖定和互斥等使使用者程式碼混亂。這意味著任何接收到食物吊艙的鳥都是免費的在沒有來自任何其他鳥類的爭用或干擾的情況下對該食品盒進行任何改變。在做出任何必要的改變之後,該鳥可以將其食物吊艙放回TupleTree,在那裡不同種類的鳥會吃它並進行改變。

平行思維的簡單範例

ConcX提供的Addx場景是Avian計算概念如何生成更簡單的並行程式碼的直接示例。Addx場景的目標是通過對每個值執行一系列數學運算來處理一系列值,直到計算出最終值並儲存為止。數學運算必須始終以相同的順序執行。

在標準的順序編碼中,我們將通過獲取下一個值,執行第一個數學運算,然後第二個數學運算,然後第三個數學運算等開始視覺化一個迴圈,直到計算出最終值為止,該值為儲存,然後迴圈重複。看起來相對簡單,並且執行速度儘可能快。其最大吞吐量取決於執行單執行緒的一個處理器的速度。

為了更快速地處理更多的值,需要使用多個處理器,這就是棘手的問題。正常的解決方案是建立一個執行緒池,每個執行緒執行上述的順序程式碼。但是這會使處理複雜化,因為並行程式碼必須 確保輸入值僅由一個執行緒處理,並且不會跳過輸入值,同時確保不會發生死鎖和活鎖。很難想象執行緒可能會互相干擾的所有可能的方式 - 在客戶的站點上展示了多次新的令人驚訝的失敗模式。更不用說必須為每個執行時環境(膝上型電腦vs大型機等)預先配置和編譯多個版本的應用程式。

Addx(Avian)解決方案配置了一個任意數量的鳥群,每隻鳥只吃一種食物,並且在將其作為不同型別的食物放回之前,只對該食物執行一次數學運算。通過適當配置食物和儲存的食物,保證數學操作的正確順序。例如,Bird1吃Food1,對其執行數學運算,並將其儲存為Food2。Bird2吃Food2,對它進行數學運算,並將其作為Food3儲存。Bird3吃Food3,等等。這也可以更簡潔地表達為:

食物1 - > Bird1 - > FOOD2 - > BIRD2 - > Food3 - > Bird3。。。.Foodn - > Birdn。

以下簡化圖說明了Avian並行性。

  • 在下面的生命週期1中,所有五隻鳥在大約同一時間開始飛行,但只有Add1Bird找到任何食物。它對該值執行操作,然後將其作為只有Add2Bird吃的食物放回到TupleTree中。

  • 在生命週期2中,Add1Bird和Add2Bird都可以找到食物,以便他們都執行各自的操作,然後將其食物儲存回TupleTree。

  • 在生命週期3中,Add1Bird,Add2Bird和Add3Bird都可以找到它們的食物種類,處理它們並將它們放回到TupleTree中。

像鳥一樣思考更好的並行程式設計

大約第五個迴圈通過它們的生命週期(找到食物,消化它,儲存它和午睡),所有五隻鳥同時從TupleTree進食,處理它們的莢,並將它們更新的莢儲存在樹中。上面只畫了5只鳥,但很容易想象將這個圖放大到包括20只或50只或100只鳥,它們都將同時執行(飛行),所有這些都遵循相同的簡單和自然的模式。就像真正的鳥類一樣,如果任何鳥類尋找食物並且沒有找到它,它就會等待一會兒,然後再次嘗試。

重要提示:如圖所示這鳥不步調一致操作的簡化圖。每隻小鳥以其自己的個體速率生活,因為每次小睡時,它會隨機選擇一段時間(在可配置的範圍內)。這意味著隨機短時間小睡的小鳥會比隨機長時間小睡的小鳥更快地完成其生命週期。隨著時間的推移,午睡的時間長短會趨於平緩,所以一段時間以後會很慢。在現實生活中,Add5Bird(或任何其他鳥)開始吃之前可能需要3或10或15個週期。

配置鳥類

ConcX提供GUI螢幕來新增,配置和啟動鳥類。GUI螢幕還可以在鳥兒飛行時提供動態的實時狀態更新。以下螢幕截圖顯示了執行Addx場景的五隻小鳥。螢幕右側的進度條實時顯示每隻鳥的成功。每隻鳥的進度條越長,鳥成功吃的次數就越多。

像鳥一樣思考更好的並行程式設計

由於每隻鳥都有使用者可選擇的食物型別,因此重新排列數學運算的順序很簡單。只需更改選定的食物並重新執行即可。如果任何鳥的配置不合適,它將無法找到食物,其進度條也不會增長。

“食物供應”選項卡包含食物容器進度條,可以實時動態顯示可用食物容器的數量。當執行結束時,TupleTree選項卡顯示其包含的食物莢的時間戳列表以及每個食物莢內容的簡要摘要以及每個食物莢和哪些鳥執行的交易。

上述功能都整合到併發資源管理器中,允許您互動式地探索和開發並行程式。一旦你瞭解瞭如何將程式分解為可以並行執行的子步驟,則可以使用所選擇的程式語言對應用程式進行編碼。

使用程式碼

下面顯示了Add3Bird的完整Java程式碼。它只有43行,幾乎一半(19)的行可以是註釋或空白(用於視覺分離的空白或單個花括號)。Add3Bird所需的唯一程式碼是afterDigestion方法的重寫,它所做的只是將3新增到它找到的任何非空食品盒中。查詢窗體並將其儲存回樹中都由BasicBird框架處理,使開發人員的工作變得更輕鬆。

像鳥一樣思考更好的並行程式設計

對於上面的程式碼最重要的是,在這段程式碼中沒有鎖定或同步或互斥,因為它全部由TupleTree和ConcX框架處理。所有的多執行緒並行程式碼都在後臺進行管理,因此使用者可以專注於如何將主要任務劃分為鳥類可以並行處理原子的小尺寸碎片。

雖然上述任務可能看起來過於簡單,但它實際上只是更復雜場景的模板。例如,如果Add1Bird被一隻抓住10毫秒聲音的鳥取代並且Add2Bird被替換為對其執行快速傅立葉變換的鳥並且Add3Bird被替換為試圖將所得輸出與其他先前處理的結果等。如果第二隻鳥跟不上第一隻鳥,而不是試圖修改它以加快執行速度(並且可能引入錯誤),那麼首選的Avian解決方案就是新增另一個例項(或另外10個例項)第二隻鳥。

興趣點

Avian Computing的開發旨在鼓勵使用者基於天生平行的模型(例如鳥群)來形象化他們的並行程式。蜜蜂蜂群,魚群或馬群也可以作為模型,因為它們都包含多個獨立執行並且非同步執行的角色,同時也可以一起工作。

ConcX是由開發人員/實驗者共同建立的。這是一個互動式環境,允許使用者啟動和停止鳥類的各種組合和配置。雖然每隻鳥的飛行都有一個不斷更新的進度條,以顯示它的成功程度和可用的食物供應量。飛行結束後,可以檢查雞群的結果以及每隻雞的事件歷史記錄。

Avian Computing和ConcX實現的概念旨在成為培訓輪子,幫助我們的單執行緒思維思考並討論並行程式。

要詳細瞭解Avian Computing的基本概念以及為什麼我們需要幫助來思考並行程式,請訪問Avian Computing網站。如果您準備嘗試一下,可以從Avian網站或SourceForge下載ConcX-2.x.zip(jar檔案,lib檔案和flock檔案)。請務必同時下載“Avian Computing入門指南”使用者指南,因為它包含安裝資訊以及大約十幾種並行方案,例如平行計算Pi,用餐哲學家Probelm,BarberShop場景等。

針對上面的技術我特意整理了一下,有很多技術不是靠幾句話能講清楚,所以乾脆找朋友錄製了一些視
頻,很多問題其實答案很簡單,但是背後的思考和邏輯不簡單,要做到知其然還要知其所以然。如果想
學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以
加我的Java進階群:744642380,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的視訊免費分
享給大家


相關文章