從並行計算的角度,MPI 與 OpenMP 的對比?
就是想更好的對比兩者之間的不同,當然入門一點最好。我要幫導師做這樣的伺服器,正在入手過程中。
兩者區別很多人都提到了,至於兩者的選擇和性能,很多人有些誤解。
"多台機器,每台都是多核,那自然就是 OpenMP +
MPI",沒那麼自然。很多人以為SMP集群openmp+MPI混編性能最好,那都是有些想當然了,覺得MPI需要通信拷貝操作,所以性能差。業界實際測試過的人,都知道一般來說,純MPI性能比純openmp和MPI+openmp混合都要好很多,只是內存佔用會大一些。原因是集群普遍是NUMA節點,節點內的data
locality對於openmp是一個大問題。而MPI編程模型天生強制比較好的data
locality。當然openmp結合affinity設置也能寫出來locality好的程序,但是普遍的說法是,如果你想用openmp寫出MPI的性
能,那你的openmp代碼肯定長得像MPI代碼。具體做法就是把mpi的通信,用openmp數據複製替代,還不如直接用MPI得了,至少可以擴展到分散式。
還有一個做法就是每個numa單元一個MPI進程,numa單元內部用openmp。這樣需要比較複雜的cpu binding設置,但是是可以部分解決locality問題的。
openmp+MPI混合編程在MPI基礎上加大了複雜度,採用它的目的,是減少內存佔用,而非提高性能。即使是在單個節點,純粹的共享內存系統,MPI程序在性能上也不輸openmp,大多數時候甚至更好。
補充:
本來是對一位知友評論的回復裡面的一部分,感覺可以作為答案的補充,貼過來如下mpi的很多實現有針對共享內存系統優化的,節點內並非是跟跨節點一樣的網路通信,會變成直接的內存拷貝。比如openmpi的vader blt方式就是共享內存通信,延遲低帶寬高。
OpenMP和MPI是並行編程的兩個手段,對比如下:
- OpenMP:線程級(並行粒度);共享存儲;隱式(數據分配方式);可擴展性差;
- MPI:進程級;分散式存儲;顯式;可擴展性好。
OpenMP採用共享存儲,意味著它只適應於SMP,DSM機器,不適合於集群。MPI雖適合於各種機器,但它的編程模型複雜:
- 需要分析及劃分應用程序問題,並將問題映射到分散式進程集合;
- 需要解決通信延遲大和負載不平衡兩個主要問題;
- 調試MPI程序麻煩;
- MPI程序可靠性差,一個進程出問題,整個程序將錯誤;
首先OpenMP和MPI的區別在於針對的是不同的內存模型,二者並非水火不容。恰恰相反,很多時候要兩者同時使用來達到最好的性能。
OpenMP的內存模型是統一/共享的內存模型(unified/shared memory),比如你的筆記本的電腦CPU有4個核心但只有一個共同的內存,各個核心通過內存來分享交換數據。MPI不僅可以用於上述unified/shared memory,更多用於distributed memory,比如你有一個集群8台伺服器,每台伺服器有各自的CPU和內存,需要通過乙太網/Infiniband交換數據。
上面很多朋友都說MPI複雜,OpenMP更簡單,其實未必。
所謂MPI複雜是指需要程序員手動管理數據是怎麼partition的,並且要手動實現進程之間的相互通信(例如MPI_Send, MPI_Recv),以及維持同步(scynchronization, 例如MPI_Barrier),但這一切都是盡在程序員掌握之中的。
OpenMP你只要在程序適當位置#pragma就好了,編譯器以及動態庫幫你把數據partition,確實方便省事兒。然而風險在於如果你的#pragma沒有寫好,很容易產生data race,而且編譯器根本不會提示你,程序還是照樣能跑,只不過跑出來的結果可能會差了十萬八千里。(別問我怎麼知道的,都是淚)
至於二者性能,前幾天看了一篇論文[1]里有一個圖很直觀:(只是針對一個benchmark,實際性能還要看具體應用)
一看日期,這個問題比較早了,可能現在回答有點遲,我就從實際情況來回答吧.
首先,應用並行計算的目的,主要針對計算密集型任務,利用並行計算,減少計算時間.那麼,採用哪種合適的並行運算庫,就應該取決於目標任務的所需要的計算量,畢竟,並行化後的計算時間,可以簡單地看做是成比例縮小的.比如串列任務需要360小時,那麼,4核並行化後大約90小時,36核可能大約就10小時了.
然後,再觀察OpenMP和MPI的兩種並行運算庫的特性, @李超錚已經總結的很好了.那麼,若是簡單地需要縮小到個位數以內的時間,那麼,OpenMP可能是更好的選擇,學習成本低,硬體投入也簡單,買個好一點的工作站,相對於常用的筆記本,就可以很明顯的縮短計算時間.但若是想要幾十倍,甚至成百倍的提高計算能力,OpenMP這種需要所有CPU共享相同內存的模型,就不適用了,這時,MPI這種分散式計算模型就更為適用,特別是利用超級計算機集群進行計算時.
最後,其實這類計算密集型任務,可能利用OpenCL可能更為合適,雖然有一定的學習成本,但模型比MPI簡單,擴展性比OpenMP更好,更關鍵的,是目前各個並行計算廠商都在支持的實際標準(de facto standard),適用於CPU和GPU平台,雖然轉移平台仍需要人工去做一定修改,但OpenMP和MPI只支持CPU平台.特別的,如今一塊頂級GPU的浮點數計算能力已經達到了我所在學校2004年建設的半個超級計算機集群的運算能力(50台).最近幫我家姑娘複習期末考試的內容,於是順便看了一下
我認為,要理解OpenMP和MPI,首先要有一些操作系統知識和系統編程基礎——OpenMP對應的實際上是單進程多線程的並發編程模型,可以將一個單線程的程序按for循環拆分成多線程——相當於pthread_create。
對於同一個進程的多個線程來說,由於它們只是獨佔自己的棧內存,堆內存是共享的,因此數據交換十分地容易,直接通過共享變數就可以進行交換,編程模型非常簡單易用,並且對於操作系統來說,線程的上下文切換成本也比進程低很多。然而另一方面,由於線程不能脫離進程獨立存在,而一個進程不能存在於多台機器上,所以OpenMP只適用於擁有多個CPU核心的單台電腦。並且多線程編程存在臨界區(Critical Section),需要你自己去加鎖,解決Race Condition問題,否則的話很容易導致不可預知的後果。
而MPI則是多進程的並發編程模型,相當於你自己調用fork——每一個進程的內存地址空間都是獨立的,它們彼此之間幾乎什麼都不共享,只能通過進程間通信(IPC)來交換彼此的數據,因此編程難度明顯要大很多。MPI有一個非常顯著的優點,那就是對於一個分散式系統來說,進程是可以在分散式系統的每一台電腦之間轉移的,因此對於擁有多台電腦的分散式系統來說,其並發性要明顯好於OpenMP。
Openmp
簡單。不用大改源程序,直接加#pragma就行了。只適用於共享式內存。比如一台電腦,4核cpu共享16G內存,可以用Openmp啟動4核同時計算。MPI稍複雜。需要重新設計程序,學習成本稍高。擴展性好,適用於共享式或者分散式內存(樓上所說有誤)。比如二台電腦,各有4核cpu和16G內存,可以用MPI同時在二台電腦上計算,並且每台電腦都同時使用各自的4核,和16G內存(相當於8核同時計算)。因此你在一台電腦上寫出的程序,也可以方便的使用在計算機集群中。openmp適合對原有的串列代碼進行並行化改造,新項目還是用mpi好一些,一個是適應的硬體條件廣泛,速度也比較快,openmp當線程數超過一定數量,比同樣進程數的mpi慢。
一個是進程級,一個是線程級
MPI+openMP往往是組合使用,CPU對應MPI,CPU內多核對應openMP。
你問的不是非常清楚,建伺服器和這兩個編程模型哪個好,不是一個問題。
多台機器,每台都是多核,那自然就是 OpenMP + MPI。如果你們打算買編譯器,那麼運行時庫都會在裡面。如果用開源編譯器,比如 gcc,你需要自己編譯安裝開源的 runtime library ,比如 OpenMPI.
至於把普通單線程程序 port 成這兩個模型,那就是另一番學習的過程了。推薦閱讀:
※為什麼超級計算機比集群貴?
※請問pcie x16/x8以及sli/cfx對運算卡性能的影響?
※有哪些好用的開源並行線性矩陣求解器?
※為什麼伺服器linux下用openmp結果比單線程還要慢?
※哪些因素限制了ANSYS Fluent的並行核數?
TAG:並行計算 |