超線程(Hyper-Threading)和OpenMP

現在的單處理器系統使用指令級的並行機制(ILP)在執行流水線的不同硬件功能中同時執行多條指令。 Intel®  Xeon®  processor enhances ILP through speculation, which permits dynamic, out-of-order execution of instructions. The performance of single-processor systems, such as those based on the Intel Xeon processor, can be improved by adding more CPU resources.

現在的共享內存多處理器系統使用ILP機制,但是還可以利用線程級的並行機制(TLP)。TLP不僅可以允許並行執行指令,而且可以並行執行線程,這可以幫助大幅度提高多線程應用運行的速度。TLP的最終目標是以更少的時間完成更多的工作,減少整個應用的運行時間。
雖然添加更多的處理器將會提高共享內存的多處理器系統的性能,但這個解決方案更爲昂貴。從另一個角度來看,利用Intel超線程和OpenMPTM  應用編程接口(API)等技術實現的多任務、多線程和羣集,也會達到提高性能的目的。
利用超線程技術來支持TLP
超線程技術用來消除單處理器和多處理器系統之間的差異,即在單處理器系統中支持TLP機制。超線程技術可以使得在操作系統和相關的應用看來,一個物理處理器像是兩個(邏輯)處理器。多處理器系統也可以利用多線程技術的優勢,使每個處理器看作是兩個處理器。因此,一個Intel Xeon處理器平臺將被看作是一個雙處理器的系統,一個雙Intel Xeon處理器的平臺將被看作是一個四處理器的系統,依此類推。
在傳統的多處理器平臺中,多個CPU使用他們自己的體系狀態和執行資源,但TLP機制不同,每個支持超線程的處理器包括兩個體系狀態,可以共享一組處理器執行資源。超線程技術爲多線程應用提供更多的的計算能力,同時還可以更好地利用硬件資源。
利用OpenMP提供更多的並行機制
OpenMP是一個便攜的可擴展的標準,爲程序員提供了一個簡單和靈活的接口,可以方便地爲共享內存的多處理器平臺增加並行機制。計算機硬件、軟件和工具製造商,例如Intel,DEC,Silicon Graphics,Kuch & Associates和IBM早在15年前就聯合定義了OpenMP標準。OpenMP在所有的架構上都支持使用C/C++和FORTRAN進行共享內存並行編程,包括基於Microsoft® WindowsNT® 和UNIX® 操作系統的構架。OpenMP還使用編譯器指令和庫函數,幫助並行應用程序員使用C/C++和FORTRAN創建多線程應用。
何時使用OpenMP
對於包含有多個耗時的循環的應用,OpenMP特別有用,它可以將工作劃分爲多個線程。任一應用中劃分粗糙的循環級別的並行機制的數量往往比較有限,限制了應用程序的可擴展性。一個並行區域可能嵌入在其它並行區域之內,但是它們缺省的執行方式是必須使用一個線程組來串行執行。
OpenMP允許程序員使用劃分良好的循環級並行機制來擴展應用,實現多處理。它們可以添加劃分粗糙的並行機制,同時仍然能保留以前在擴展方面所做的投資。使用這種增量式的開發戰略,程序員可以避免轉向消息傳遞或其它並行編程模型時所具有的風險。
如何編寫OpenMP程序
要開發新的應用,程序員必須分析原始問題,將它分解爲多個使用共享和本地數據的任務,確定數據之間的依賴性,然後重新組織任務進入執行單元的順序,這可以使用並行編程環境來實現編碼(見 圖1 )。對於現有的應用,程序員可以使用一個配置分析工具,例如Intel VTuneTM 性能分析器,找到程序中消耗時間較多的地方。
圖1.
圖1. 編寫並行程序的方法
程序員可以使用一個並行應用程序庫來完成他們的大多數工作,調用定義得很好的庫函數。對於其它類型的應用,可以使用並行API。程序員在使用多線程時應當遵循如下策略:
  • 使用線程池
  • 活動線程不要使用太多(可用線程的數量等於處理器的數量)
  • 使用粗糙劃分的線程,而不是精細劃分的線程
  • 最小化同步
  • 不要使用"錯誤共享"緩存線
OpenMP編程模型的運作方式
OpenMP使用fork-join並行機制,程序首先順序執行,然後轉換成爲並行程序。這個程序開始時先是一個主線程,然後在遇到用戶定義的並行區域時創建一組線程 (見 圖2 ).
圖2.
圖2. Fork-join並行機制
在並行區域之內,多個線程可以執行相同的代碼塊,或使用工作共享結構體並行執行不同的代碼段。在結構體的末尾的障礙點將出現線程同步。雖然非結構化的塊可以擁有多個入口和多個出口(見 圖3 ),但結構化的塊僅僅在頂部有一個入口,在末尾有一個出口(見 圖4 )。唯一的例外就是程序結束 - 在FORTRAN和C/C++中分別是STOP和exit()命令,這些命令是唯一允許在塊內使用的分支。在結構化塊的出口處,進行一次內存flush操作,在這次操作中,所有的線程都將可見的變量回寫到內存中,從而將所有的線程返回到一個公共的已知狀態。
圖3.
圖3. 非結構化塊舉例
圖4.
圖4. 結構化塊舉例
使用OpenMP API
程序員可以使用omp parallel pragma在OpenMP中創建線程。例如,下面的代碼展示瞭如何創建一個三線程的並行區域:
float array[N];
int ID;
//function requests 3 threads
omp_set_num_threads(3);
#pragma omp parallel
{
//function returns thread ID
ID = omp_get_thread_num();
div_func(array, ID);
}
printf("Done.\n");
每個線程將都將執行結構化塊內的代碼,最後,每個線程將冗餘地調用div_func(array,ID),其中ID=0到2(見 圖5 )。所有的線程都共享一份數組變量,並將在打印語句(障礙)之前重新集合。
圖5.
圖5. OpenMP並行區域中的線程流
共享數據與私有數據的比較
因爲OpenMP是一個共享內存的編程工具,在並行區域之前定義的大多數變量都是全局變量 - 將在線程之間共享。但是,有些變量屬於線程私有的,例如並行區域調用的子程序的局部變量或一個語句塊內的自動變量。指令中的語句可以聲明共享或私有數據。在圖6 中,聲明的變量array、j和k在所有線程之間共享,而temp對於每個線程來說是局部變量。
圖6.
圖6. 共享數據和私有數據的比較實例
工作共享結構體
圖7 中,for工作共享結構體將循環劃分到一組線程中。工作共享結構體不僅可以使多線程的編碼更爲高效,而且可以簡化多線程的代碼。在圖8 演示了這一效果。
圖7.
圖7. 工作共享結構體舉例
圖8.
圖8. 並行區域中工作共享和OpenMP的效率
缺省情況下,障礙存在於omp for pragma的末尾。程序員可以使用nowait語句來取消這一障礙。
減少循環的依賴性
循環必須獨立於工作共享纔能有效。參考 圖9 的公共循環。變量res創建了一個循環依賴性,並行操作將無法運行。因此,程序員必須使用一個減小語句,見 圖10 ,才能並行執行循環。
圖9.
圖9. 循環依賴性舉例
圖10.
圖10. 使用OpenMP減少的循環依賴性的舉例
圖10 的循環中,每個線程都擁有自己的res拷貝,它累計結果。在循環之後,私有拷貝將綜合到一份共享拷貝中。
使用OpenMP編譯
Intel C++和FORTRAN編譯器(都是6.0版)中包括最新的支持OpenMP(1.0版的API)的功能。如圖11 所示,這些編譯器中包括一個自動並行機制開關(-Qparallel)和OpenMP開關(-Qopenmp)。程序員可以使用-Qparallel開關來編寫他們不想使用OpenMP指示符來優化的代碼。
圖11.
圖11. Intel編譯器中用於自動並行和OpenMP指示符的優化開關
例如,如果軟件提供商沒有時間和人員來跟蹤原始源代碼和創建OpenMP並行結構體,但想利用共享內存多處理系統中的並行機制來編程,他們可以在重新編譯代碼的時候使用-Qparallel開關。-Qparallel開關使編譯器可以自動發現能夠並行處理的代碼區域。但是,讓編譯器作出這種決定在完善性和效率上可能比不上手動使用OpenMP進行優化所具有的性能。
自動並行化和SPECviewperf基準
程序員在使用SPECviewperf®  7.0基準時,必須使用自動並行開關,這種方式能在不更改源碼的情況下優化代碼。圖12 shows the performance gain acquired by using the -Qparallel switch and Hyper-Threading technology. These results were relative to the performance of a single processor without Hyper-Threading technology. Using that processor's SPECviewperf performance as the baseline, the benchmark tested a single, Hyper-Threading-enabled Intel Xeon processor at 2.0 GHz and two Intel Xeon processors at 2.0 GHz without Hyper-Threading enabled-both configurations used the auto-parallelization switch.
圖12.
圖12. 使用自動並行開關和超線程技術的SPECviewperf性能
SPECviewperf基準測試結果表明使用自動並行開關來替代標準(沒有並行處理)代碼將會獲得很高的性能增益。在單處理器配置中使用超線程技術對性能有積極的影響;從理論少上看,它的性能幾乎與兩個物理處理器系統的性能相當。正如SPECviewperf基準的ugs-10模型所得到的結果,不是所有的測試將會從自動並行處理中受益,所能獲得性能增益是與具體代碼相關的。每個程序代碼可能會受益,也可能不能受益。但是如果速度對於最終用戶來說很重要,使用自動並行開關來重新編譯將是值得一做的。
OpenMP指令和Linpack基準
如果時間和資源允許,推薦使用OpenMP結構體和-Qopenmp開關。程序員對自己的代碼總是特別瞭解,他們清楚那些代碼區域會從OpenMP中受益。圖13 表明在具有兩個2.0GHz的Intel Xeon處理器的平臺在支持和不支持超線程技術運行的情況下,使用OpenMP指示符所帶來的Linpack基準性能的變化。這些測試結果展示了在使用OpenMP並行技術和超線程技術時代碼的行爲。如果取消使用超線程,標準代碼和使用OpenMP的代碼兩者之間幾乎沒有差異。但是,如果啓用了超線程,標準代碼的性能將會下降,OpenMP代碼的性能將超過標準代碼的性能。同時使用OpenMP代碼和超線程技術的性能也將超過沒有使用超線程的標準代碼和OpenMP代碼的性能。
圖13.
圖13. 使用OpenMP並行和超線程技術的Linpack性能
增強處理器性能
OpenMP是一些易於使用的API,用來編寫多線程程序。它不再需要用戶處理重複分區、數據共享以及線程計劃和同步的底層細節。配置工具,甚至更爲簡單的測試和發現錯誤,都會有助於確定哪些代碼將會從OpenMP中受益。而且,如果組合使用OpenMP和Intel Xeon處理器的超線程技術,將會是獲得更強大的計算能力的經濟高效的選擇。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章