《Python分布式計算》第1章 并行和分布式計算介紹 (Distributed Computing with Python)


序言
第1章 并行和分布式計算介紹
第2章 異步編程
第3章 Python的并行計算
第4章 Celery分布式應用
第5章 云平臺部署Python
第6章 超級計算機群使用Python
第7章 測試和調試分布式應用
第8章 繼續學習


本書示例代碼適用于Python 3.5及以上。


當代第一臺數字計算機誕生于上世紀30年代末40年代初(Konrad Zuse 1936年的Z1存在爭議),也許比本書大多數讀者都要早,比作者本人也要早。過去的七十年見證了計算機飛速地發展,計算機變得越來越快、越來越便宜,這在整個工業領域中是獨一無二的。如今的手機,iPhone或是安卓,比20年前最快的電腦還要快。而且,計算機變得越來越小:過去的超級計算機能裝下整間屋子,現在放在口袋里就行了。

這其中包括兩個重要的發明。其一是主板上安裝多塊處理器(每個處理器含有多個核心),這使得計算機能真正地實現并發。我們知道,一個處理器同一時間只能處理同一事務;后面章節我們會看到,當處理器快到一定程度,就可以給出同一時間進行多項任務的假象。若要真正實現同一時間多任務,就需要多個處理器。

另一項發明是高速計算機網絡。它首次讓無窮多的電腦實現了相互通訊。聯網的電腦可能處于同一地點(稱為局域網LAN)或分布在不同地點(稱為廣域網WAN)。

如今,我們都已熟悉多處理器/多核心計算機,事實上,我們的手機、平板電腦、筆記本電腦都是多核心的。顯卡,或圖形處理器(GPU),往往是大規模并行機制,含有數百乃至上千個處理單元。我們周圍的計算機網絡無處不在,包括:Internet、WiFi、4G網絡。

本章剩余部分會探討一些定義。我們會介紹并行和分布式計算的概念。給出一些常見的示例。探討每個架構的優缺點,和編程的范式。

在開始介紹概念之前,先澄清一些東西。在剩余部分中,除非特別指明,我們會交叉使用處理器和CPU核心。這在概念上顯然是不對的:一個處理器會有一個或多個核,每臺計算機會有一個或多個處理器。取決于算法和性能要求,在多處理器或單處理器多核的計算機上運行可能會有速度上的不同,假定算法是并行的。然而,我們會忽略這些差異,將注意力集中于概念本身。

并行計算

并行計算的概念很多。本書提供一個簡潔的概念:

并行計算是同時使用多個處理器處理事務。

典型的,這個概念要求這些處理器位于同一塊主板,以區別于分布式計算。

分工的歷史和人類文明一樣久遠,也適用于數字世界,當代計算機安裝的計算單元越來越多。

并行計算是有用且必要的原因很多。最簡單的原因是性能;如果我們要把一個冗長的計算分成小塊、打包給不同的處理器,就可以在相同時間內完成更多工作。

或者,并行計算在處理一項任務時,還可以向用戶呈現反饋界面。記住一個處理器同一時間只能處理一項任務。有GUIs的應用需要將任務交付給另一個處理器的獨立線程,以讓另一個處理器能更新GUI,并對輸入進行反饋。

下圖展示了這個常見的架構,主線程使用事件循環(Event Loop)處理用戶和系統輸入。需要長時間處理的任務和會阻塞GUI的任務會被移交給后臺或worker線程:

一個該并行架構的實際案例可以是一個圖片應用。當我們將數碼相機或手機連接到電腦上時,圖片應用會進行一系列動作,同時它的用戶界面要保持交互。例如,應用要將圖片從設備拷貝到硬盤上、建立縮略圖、提取元數據(拍攝日期及時間)、生成索引、最后更新圖片庫。與此同時,我們仍然可以瀏覽以前傳輸的圖片,打開圖片、進行編輯等等。

當然,整個過程在單處理器上可能是順序依次進行的,這個處理器也要處理GUI。這就會造成用戶界面反應遲緩,整個應用會變慢。并行運行可以使這個過程流暢,提高用戶體驗。

敏銳的讀者此時可能指出,以前的只有單處理器單核的舊電腦也可以(通過多任務)同時處理多個事件。即使如今,也可以讓運行的任務數超過計算機的處理器數目。其實,這是因為一個正在運行的任務被從CPU移出(這可能是自發或被操作系統強制的,例如,響應IO事件),好讓另一個任務可以在CPU上運行。類似的中斷會時而發生,在應用運行中,各種任務會相繼獲得會被移出CPU。切換通常很快,這樣,用戶就會有計算機并行運行任務的感覺。實際上,只有一個任務在特定的時間運行。

通常在并行應用中運行的工具是線程。系統(比如Python)通常對線程有嚴格的限制(見第3章),開發者要轉而使用子進程subprocess(通常的方法是分叉)。子進程取代(或配合)線程,與主進程同時運行。

第一種方法是多線程編程(multithreaded programming)。第二種方法是多進程(multiprocessing)。多進程可以看做是多線程的變通。

許多情況下,多進程要優于多線程。有趣的是,盡管二者都在單機運行,多線程是共享內存架構的例子,而多進程是分布式內存架構的例子(參考本書后續內容)。

分布式計算

本書采用如下對分布式計算的定義:

分布式計算是指同一時間使用多臺計算機處理一個任務。

一般的,與并行計算類似,這個定義也有限制。這個限制通常是要求,對于使用者,這些計算機可以看做一臺機器,進而掩蓋應用的分布性。本書中,我們更喜歡這個廣義的定義。

顯然,只有當計算機之間互相連接時,才可以使用分布式計算。事實上,許多時候,這只是對我們在之前部分的并行計算的概念總結。

搭建分布式系統的理由有很多。通常的原因是,要做的任務量太大,一臺計算機難以完成,或是不能在一定時間內完成。一個實際的例子就是皮克斯或夢工廠的3D動畫電影渲染。

考慮到整部電影要渲染的總幀數(電影兩個小時,每秒有30幀),電影工作室需要將海量的工作分配到多臺計算機(他們稱其為計算機農場)。

另外,應用本身需要分布式的環境。例如,即時聊天和視頻會議應用。對于這些應用,性能不是最重要的。最關鍵的是,應用本身要是分布式的。下圖中,我們看到一個非常常見的網絡應用架構(另一個分布式應用例子),多個用戶與網站相連。同時,應用本身要與LAN中不同主機的系統(例如數據庫服務器)通訊:

另一個分布式系統的例子,可能有點反直覺,就是CPU-GPU。如今,顯卡本身就是很復雜的計算機。它們高并行運行,處理海量計算密集型任務,不僅是為了在顯示器上顯示圖像。有大量的工具和庫(例如NVIDIA的CUDA,OpenCL和OpenAcc)可以讓開發者對GPU進行開發,來做廣義計算任務。(譯者注:比如在比特幣中,使用顯卡編程來挖礦。)

然而,CPU和GPU組成的系統實際上就是一個分布式系統,網絡被PCI總線取代了。任何要使用CPU和GPU的應用都要處理數據在兩個子系統之間的移動,就像傳統的在網絡中運行的應用。

將現存的代碼移植到計算機網絡(或GPU)不是一件輕松的工作。要移植的話,我發現先在一臺計算機上使用多進程完成,是一個很有用的中間步驟。我們會在第3章看到,Python有強大的功能完成這項任務(參考concurrent.futures模塊)。

一旦完成多進程并行運行,就可以考慮將這些進程分拆給獨立的應用,這就不是重點了。

特別要注意的是數據,在哪里存儲、如何訪問。簡單情況下,共享式的文件系統(例如,UNIX的NFS)就足夠了;其余情況,就需要數據庫或是消息隊列。我們會在第4章中看幾個這樣的實例。要記住,真正的瓶頸往往是數據而不是CPU。

共享式內存vs分布式內存

在概念上,并行計算和分布計算很像,畢竟,二者都是要將總計算量分解成小塊,再在處理器上運行。有些讀者可能會想,一種情況下,使用的處理器全部位于一臺計算機之內,另一種情況下,處理器位于不同的計算機。那么,這種技術是不是有點多余?

答案是,可能。正如我們看到的,一些應用本身是分布式的。其它應用則需要更多的性能。對于這些應用,答案就可能是“有點多余”——應用本身不關心算力來自何處。然而,考慮到所有情況,硬件資源的物理存放地點還是有一定意義的。

也許,并行和分布式計算的最明顯的差異就是底層的內存架構和訪問方式不同。對于并行計算,原則上,所有并發任務可以訪問同一塊內存空間。這里,我們必須要說原則上,因為我們已經看到并行不一定非要用到線程(線程是可以訪問同一塊內存空間)。

下圖中,我們看到一個典型的共享式內存架構,四個處理器可以訪問同一內存地址。如果應用使用線程,如果需要的話,線程就可以訪問同一內存空間:

然而,對于分布式應用,不同的并發任務不能正常訪問同一內存。原因是,一些任務是在這一臺計算機運行,一些任務是在另一臺計算機運行,它們是物理分隔的。

因為計算機之間可以靠網絡通訊,可以想象寫一個軟件層(中間件),以一個統一的內存邏輯空間呈現應用。這些中間件就是分布式共享內存架構。此書不涉及這樣的系統。

下圖中,我們還有有四個CPU,它們處于共享內存架構中。每個CPU都有各自的私有內存,看不到其它CPU的內存空間。四臺計算機(包圍CPU和內存的方框)通過網絡通訊,通過網絡進行數據傳輸:

現實中,計算機是我們之前講過的兩種極端情況的結合體。計算機網絡通訊就像一個純粹的分布式內存架構。然而,每臺計算機有多個處理器,運行著共享式內存架構。下圖描述了這樣的混合式架構:

這些架構有各自的優缺點。對于共享式內存系統,在單一文件的并發線程中分享數據速度極快,遠遠快過網絡傳輸。另外,使用單一內存地址可以簡化編程。

同時,還要注意不要讓各個線程發生重疊,或是彼此改變參數。

分布式內存系統擴展性強、組建成本低:需要更高性能,擴展即可。另一優點是,處理器可以訪問各自的內存,不必擔心發生競爭條件(競爭條件指多個線程或者進程在讀寫一個共享數據時,結果依賴于它們執行的相對時間的情形)。它的缺點是,開發者需要手動寫數據傳輸的策略,需要考慮數據存儲的位置。另外,不是所有算法都能容易移植到這種架構。

阿姆達爾定律

本章最后一個重要概念是阿姆達爾定律。簡言之,阿姆達爾定律是說,我們可以盡情并行化或分布化計算,添加算力資源獲得更高性能。然而,最終代碼的速度不能比運行在單處理器的單序列(即非并行)的組件要快。

更正式的,阿姆達爾定律有如下公式。考慮一個部分并行的算法,稱P為并行分量,S為序列分量(即非并行分量),P+S=100%T(n)為運行時間,處理器數量為n。有如下關系:

這個公式轉化成白話就是:在n個處理器上運行這個算法的時間大于等于,單處理器上運行序列分量的時間S*T(1)加上,并行分量在單處理器上運行的時間P*T(1)除以n

當提高處理器的數量n,等式右邊的第二項變得越來越小,與第一項對比,逐漸變得可以忽略不計。此時,這個公式近似于:

這個公式轉化成白話就是:在無限個處理器上運行這個算法的時間近似等于序列分量在單處理器上的運行時間S*T(1)

現在,思考一下阿姆達爾定律的意義。此處的假定過于簡單,通常,我們不能使算法完全并行化。

也就是說,大多情況下,我們不能讓S=0。原因有很多:我們可能必須要拷貝數據和/或代碼到不同的處理器可以訪問的位置。我們可能必須要分隔數據,將數據塊在網絡中傳輸。可能要收集所有并發任務的結果,并進行進一步處理,等等。

無論原因是什么,如果不能使算法完全并行化,最終的運行時間取決于序列分量的表現。并行化的程度越高,加速表現越不明顯。

題外話,完全并行通常稱作密集并行(Embarrassingly parallel),或者用政治正確的話來說,愉悅并行(pleasantly parallel),它擁有最佳的擴展性能(速度與處理器的數量呈線性關系)。當然,對此不必感到尷尬!不幸的是,密集并行很少見。

讓我們給阿姆達爾定律添加一些數字。假定,算法在單處理器耗時100秒。再假設,并行分量為99%,這個數值已經很高了。添加處理器的數量以提高速度。來看以下計算:

我們看到,隨著n的提高,加速的效果不讓人滿意。使用10個處理器,是9.2倍速。使用100個處理器,則是50倍速。使用1000個處理器,僅僅是91倍速。

下圖描述了倍速與處理器數量的關系。無論使用多少處理器,也無法大于100倍速,即運行時間小于1秒,即小于序列分量運行的時間。


阿姆達爾定律告訴我們兩點:我們最快可以將倍速提高到多少;收益減少時,何時應該減少硬件資源的投入。

另一有趣的地方是阿姆達爾定律適用于分布式系統和混合并行-分布式系統。這時,n等于所有計算機的處理器總數目。

隨著能接觸的系統的性能變得越來越高,如果能使用剩余性能,還可以縮短分布式算法運行的時間。

隨著應用的的執行時間變短,我們就傾向于處理更復雜的問題。對于這樣的算法進化,即問題規模的擴大(計算要求的擴大)達到可接受的性能時,稱作古斯塔夫森定律。

混合范式

我們現在能買到的電腦大多是多處理器多核的,我們將要寫的分布式應用就是要這樣的電腦上運行。這使得我們可以既開發分布式計算,也可以開發并行式計算。這種混合分布-并行范式是如今開發網絡分布應用的事實標準。現實通常是混合的。

總結

這一章講了基礎概念。我們學習了并行和分布式計算,以及兩個架構的例子,探討了優缺點。分析了它們是如何訪問內存,并指出現實通常是混合的。最后講了阿姆達爾定律,它對擴展性能的意義,硬件投入的經濟考量。下一章會將概念轉化為實踐,并寫Python代碼!


序言
第1章 并行和分布式計算介紹
第2章 異步編程
第3章 Python的并行計算
第4章 Celery分布式應用
第5章 云平臺部署Python
第6章 超級計算機群使用Python
第7章 測試和調試分布式應用
第8章 繼續學習


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容