MPI(信息傳遞接口) 是真正的並行編程標準,包括多節點集羣和多核 CPU 節點。web
MPI 基於分佈式內存系統和並行處理的概念算法
進程間通訊經過使用信息傳遞和大量通訊 API 庫數據庫
對於低級的通用 GPU 編程,最流行的是 CUDA 和 OpenCL。大體思路是編程
以網格形式對處理過程進行建模。一個網格中包含線程塊,線程塊中包含若干個線程服務器
塊中的線程並行執行,且能夠相互之間進行同步網絡
塊和塊之間獨立運行架構
CUDA 在 GPU 方面只針對 NVIDIA 的 GPU, OpenCL 能夠在多種 GPU 和 CPU 上運行負載均衡
新的解決方案要知足的條件框架
一個新的統一的、多層次的、具備自適應能力的框架。該框架可以對簡單的和複雜的處理流進行建模和執行,同時可以在由 CPU 和 GPU 組成的的節點組成的集羣中實現跨集羣計算socket
易於使用的 GUI。它能設計和重用並行應用
自動調度
能插入專用的調度算法
多種可重用的組件庫。上至高級應用,下至底層的 CPU 和 GPU 內核
創新點
框架更具備通常性 —— 考慮到了集羣中的接入節點和計算節點
在內部網絡中,只有接入節點能訪問多個節點
能經過使用 GUI 將應用定義爲一個工做流
能夠插入各類優化器,從而調節性能
以圖形方式創建並行應用模型。圖中節點對應計算任務,邊表明任務間的依賴關係
負責將並行應用映射到底層集羣
對集羣網絡暴露出一個統一的 API。其中,每一個集羣由一個或多個節點組成,每一個節點包含一個或多個處理器和0個或多個 GPU
說明:用戶將計算應用定義爲工做流,這會用到用戶圖形界面,同時也可能會用到模板庫中的可用組件。而後,應用被傳送到執行引擎層。該層會爲應用啓動某個優化器。優化器經過給定的優化標準決定把哪一個計算設備分配給該應用,同時根據計算和通訊開銷以及用電量等在優化器中定義的規則對應用的執行進行調度。集羣和節點管理層負責特定集羣中特定計算設備的應用執行。
用戶能夠在 KernelHive 應用層中定義將要在該系統中運行的應用。
定義一個應用只需3步
將一個工做流定義爲一個有向非循環圖,圖中的節點邏輯地鏈接着處理節點。每一個節點都包含其須要執行的代碼。整個過程能夠當作一個計算流。一開始,數據來自數據服務器,而後經過一系列的節點傳遞到有向非循環圖的最後 一個節點並保存到數據服務器中。值得注意的是, KernelHive 優化器根據給定的優化標準在每個將要執行任務的工做流節點中選擇特定的計算設備
爲每個在上一步中建立出來的節點選擇一個模版。模版是一個通用的定義,它指出了在特定節點中應該執行何種計算。模版在輸入和輸出的數量上有所不一樣,所以,處理流多是一個樹形結構。
補全在上一步中選擇出來的代碼模版。這一步經過指定一個計算內核來實施。計算內核負責節點內真正的數據處理
KernelHive 系統基於某個能讓用戶執行多種類型計算的計算模版的概念。模版自己提供了關於計算如何執行和用戶如何自定義相關細節的通用思路。框架伴隨着基本的和更高級的模版以及未來可能的額外擴展。
處理邏輯能夠爲多種多樣的 workers 定義。不一樣的 workers 對應不一樣的 KernelHive 框架模版。模版已經經過用 C++ 實現由 worker 子系統定義的抽象類 Worker。基本模版最根本的區分僅僅在於被 worker 處理的輸入和輸出量。具體包含一下3部分:
數據處理器 —— 一路輸入,執行計算,一一路輸出
數據合併器 —— 多路輸入,一路輸出
數據分割器 —— 把數據分割成多個部分
接着內核被上傳到系統,並在某個設備運行 worker 前被編譯。
每一個基礎模版只須要一個用戶定義的內核。但另外一方面,更高級的模版也許須要多個內核。例如,考慮 Master/Slave 模型。用戶要提供3個源文件 —— 一個說明輸入數據如何被分割到多個 slave 中,一個決定全部的 slave 計算說明內容,最後一個負責最終結果的合併。
用戶可使用上面提到的那些模版定義本身的計算流。模板庫包括
針對工做流圖節點的模版集。每一個模版定義節點的特色,例如內核的數量、名字和須要的輸入輸出數量。也可能用額外的模版來擴展系統
針對處理的計算內核集。系統自帶一套預約的資源文件。用戶能夠對其進行更改或添加本身的源文件。內核模版對應具體的工做流幾點模版的要求。
KernelHive GUI 應用經過圖形化的方式幫助用戶精心安排複雜的執行方案——節點表明任務,邊表明任務間的時間關係。
一個桌面應用。用於將 KernelHive 應用定義爲一個工做流,能夠用來查看計算設備的狀態和計算結果
一個 Java EE 應用,其對運行在底層集羣系統上的工做流進行優化和管理
一個 Java 守護進程。用來提供對單個集羣資源的訪問
一個 C++ 守護進程。用來提供對單個集羣節點的資源訪問。可用於控制節點中的計算設備
運行在每個鏈接到系統的計算機器中
任務:
更新機器狀態
監聽傳入的做業
一個 C++ 庫。用來在某個 HIVE_UNIT 設備上執行計算
運行在操做系統級別
被以上子系統共享的 C++ 和 Java 庫
HIVE_GUI 和 HIVE_ENGINE 部署在一臺機器上或分開部署在兩臺機器或兩個集羣上。
HIVE_UNIT 部署在每一個節點上
一個集羣中只有一個節點部署有 HIVE_CLUSTER
GUI 的做用:
1.使用可用的應用模型建立一個有向非循環圖執行方案。
節點 | 計算任務的工做流 |
---|---|
邊 | 任務間的時間關係 |
2.監視已提交的工做流執行狀態,例如:
完成
處理中
已調度
錯誤,等
3.監視系統物理節點的硬件配置
HIVE_GUI 應用於 KernelHive 系統的其餘組件進行通訊,尤爲是 HIVE_ENGINE 和 TEMPLATES 庫。
HIVE_GUI | --- | SOAP Web Services | ---> | HIVE_ENGINE |
---|
TEMPLATES 庫 被打包爲獨立的 JAR 包放在 HIVE_ENGINE 中,在應用初始化時唄動態加載。這樣就能保證 HIVE_ENGINE 和 HIVE_GUI 應用 使用的是相同版本的 TEMPLATES 庫。
集羣和節點管理層的任務:
爲了開始調度過程進程,HIVE_ENGINE 須要收集關於可用的基礎設施和他們內部狀態的信息
設法將被分配的做業發送到已經調度好的資源處,另外,發送部分或最終的計算結果。
追蹤正在進行的計算的狀態。每個 worker 按期地報告它的當前狀態和當前計算的進度。
由於 HIVE_UNIT 組件,能夠看到更多關於每一個集羣中特定計算節點的詳細信息。這些信息中包括每一個節點中可用的計算設備的數量,包括 CPU 和 GPU。OpenCL 框架容許這兩種計算設備透明地使用。
爲了知道做業的進度, HIVE_CLUSTER 經過監聽 UDP 端口來接受 HIVE_WORKER 二進制文件發來的信息。 基於 JSVC 庫實現的 HIVE_CLUSTER 做爲系統守護進程被部署。
HIVE_UNIT 經過一個 TCP 鏈接與 HIVE_CLUSTER 進行交互。HIVE_UNIT 彙報 可用設備,參數和狀態。設備列表和參數經過 OpenCL 庫的 utility 方法得到。
子系統監聽 HIVE_CLUSTER 的 connection socket
HIVE_WORKER 子系統包括多種預編譯二進制文件。這些二進制文件被分配給對應的在應用層定義好的計算模版。二進制文件的執行順序以下:
下載計算內核和輸入數據
運行內核
報告計算進度
上傳結果
向 HIVE_CLUSTER 子系統報告做業完成
每個節點在計算上花的時間有多是很大的,這對 CPU 來講不是問題,但 GPU 就會出現問題。緣由是,一般,操做系統會給顯卡分配一個 watchdog 計時器,這個計時器聯繫着每個活動的播聽任務。當顯卡運行一個任務的時間超過了給定時間,操做系統會認爲任務失敗而後殺掉該應用。一些 KernelHive 模版已經經過被設計成在迭代批處理中執行計算任務來克服這個不足。 worker 能以一種標準方式被編譯,就說,在一次運行中處理所有輸入數據,或者按照如下方案進行處理:
從頭開始或從以前保存的地方開始。一直處理輸入直到算出結果或到達迭代極限
把當前做業的偏移量存入內存,根據當前計算狀態設置進度標誌
執行宿主機器中的代碼,讀取以前保存在內存中的進度標誌。若是進度已經算出或已經處理完全部數據,則中止處理。不然,返回第一步
KernelHive能使用多種數據服務器。
讓KernelHive支持新的數據庫或文件系統時,須要實現與全部相關子系統有關的相關編程接口。好比內存數據庫和MongoDB。
由於系統的異構問題,數據格式的兼容性問題格外重要。
OpenCL標準定義了一些數據類型,這些數據類型的長度與底層的系統架構無關。int類型老是4字節,long類型老是8字節
字節順序問題也很重要。能夠經過C++模版代碼或OpenCL內核進行檢查,在兩種方法中,必需要能順利進行合適的數據轉換。
KernelHive只傳送數據地址,當相關組件須要數據時,再自行下載
HIVE_ENGINE 決定是否須要存儲數據包和是否可以刪除數據。這使得數據直接在計算單元間傳輸,而無需HIVE_CLUSTER 或 HIVE_ENGINE 的干涉。也所以減小了網絡流量。
數據包存放在分佈式的數據服務器中,那些數據服務器有些是本地 HIVE_UNIT 的一部分,有些是 HIVE_CLUSTER 的子系統。
使用 CPU 和 GPU 並行計算的機制
針對調度和選擇計算設備的可交換的插件
調度依據:性能,耗電量,可靠性
選擇最好的計算內核配置的能力
OpenCL 中網格大小的選擇
block 中線程太少,資源利用不充分
block 中線程太多,下降並行性,運行時系統會減小 block 的線程數
任務分解和自適應數據產生
要使某個節點具備分解任務的能力,用戶必須指定數據分割和合並的方式。這要求用戶必須實現 IDataPartitioner 和 IDataMerger 接口。DataPartition 產生的數據塊的數量由系統決定使用的計算單元決定。由於不一樣的計算單元的計算能力不一樣,因此,系統爲了均衡負載將產生最佳的數據塊數量。
HIVE_ENGINE 子系統是 KernelHive 的大腦和中心進入點。有關可用基礎設施和內部狀態的完整信息由 HIVE_ENGINE 收集,由 HIVE_CLUSTER 傳送。同時, HIVE_ENGINE 向客戶端運用暴露客戶端接口,尤爲是 HIVE_GUI
組件接受客戶端準備好的工做流,並把他們轉換爲單個的做業,而後把它們部署在設備上。
HIVE_ENGINE 必須可以被每個 HIVE_CLUSTER 子系統實例訪問。HIVE_CLUSTER 能更新集羣的基礎設施狀態
調度
調度進程使用一個優化器組件。該優化器組件能面向性能、耗電量、用戶正當使用資源等方面進行擴展,每個優化器都要實現 IOptimizer 接口。接口中惟一一個方法在每次有新的工做流提交時都會被執行。多個優化器能夠聯合起來工做。
開發的一個備選方案
在給定耗電量的狀況下,選出一個能使執行時間最小的節點配置。這就是一個揹包問題,使用了貪心近似算法
爲防止機器長期沒有響應,執行引擎使用了 EJB 計時器服務。TimerBean 類會週期性的檢查系統中工做流的狀態,執行清理程序,觸發工做流的再調度進程
標記爲可拆分的工做流任務會有如下幾種內核類型:
分割器內核 —— 1進多出
處理器內核 —— 1進1出
合併內核 —— 多進1出
當一個節點準備好被執行時,節點的拆分就會發生。
輸入數據會被分割成一些數據塊,這樣就能夠在 CPU 和 GPU 上進行負載均衡
而後,每一個計算設備上的一個分割器和多個處理器,一個合併任務,會使用已經定義的優化器以正確的順序被建立和調度
這樣就使得動態並行程序能經過數據塊的動態分配順利執行,同時實現資源新能差別化狀況下的負載均衡
性能調優的機制
選擇計算設備。考慮:設備性能,通訊開銷,耗電量
決定最好網格配置,主要是 GPU。系統測量不一樣配置下的執行時間,選擇最好的配置
決定首選的數據分割顆粒度和系統配置
經過機構內部開發的模擬器實現該功能,該模擬器的具體工做以下:
將給定數量的分發到計算設備中,分發時使用輪詢調度方式並考慮通訊開銷(啓動時間、帶寬)。要考慮到重疊的通訊和計算,這樣能夠減小通訊開銷和得到較高的增速
處理數據包
發送中間結果
真正的並行執行
同時有 GPU 和 CPU
每一個 CUDA 服務器上有3個 GPU,CPU 不直接參與運算
暴力破解 MD5 加密
用於計算的代碼使用 OpenCL 內核實現,這樣就能同時在 CPU 和 GPU 上運行
具備較高計算開銷和通訊開銷的應用可用來評估系統的可擴展性和用於優化的技術
GPU 內部
一個 GPU 包含 必定數量的 SM (流多處理器)
每一個 SM 有一個容許駐留線程個數的最大值和留給 OpenCL 工做組的位置數量的最大值
每一個線程必定數量的私有內存和在 OpenCL 中定義的局部內存
一個線程組中有多個線程,這使得每一個線程組都須要必定數量的私有內存和局部內存
SM 會在這些並行的線程組中運行,因此總共使用的私有內存和局部內存不會超過 SM 規定的值
測試內容
每一個 block 中線程數量不一樣時的執行時間
每一個 grid 中 block 數量不一樣時的執行時間
測試結論
當 block 中線程太少時,執行時間明顯變長
當 block 中線程數量超過一個特定值時,會形成沒必要要的開銷
異構環境下涉及到多種 CPU 和 GPU。每一個處理器的計算能力不一樣,因此須要負載均衡
時間開銷以下:
調用 Web 服務的時間,從數據服務器下載數據包的時間,
處理時間
調用 Web 服務的時間,上傳數據的時間
對於該測試而言,CPU 比 GPU 慢不少,結論:
數據包太少,GPU 先完成,而 CPU 還沒完成,那麼總的執行時間會變長
數據包太多,雖然數據包會變小,可是通訊開銷會變大,好比下載數據和上傳數據的時間
要權衡數據包的大小和數量
使用理論最優值時,執行時間直線降低。
選擇最好的數據粒度從而找出最好的乘數是頗有價值的
地理空間數據的反距離加權插值計算
數據處理節點使用 OpenCL 實現反距離加權插值算法
master--slave 模型
master -- HIVE_ENGINE
slave -- HIVE_WORKER
中間層 -- HIVE_CLUSTER 和 HIVE_UNIT
KernelHive 框架的總開銷比面向性能的 MPI + OpenCL 的總開銷高出約11%
KernelHive 框架開銷主要包括:
通訊開銷 —— web 服務
運行時開銷 —— HIVE_ENGINE 和 HIVE_CLUSTER 由 Java實現