什麼是代碼現代化?

原文地址算法

 

現代高性能計算機由下列資源組合構建而成:多核處理器衆核處理器、大型高速緩存,高帶寬進程間通訊結構和高速 I/O 功能。 高性能軟件需通過設計,以充分利用這些豐富的資源。 不管是從新構建並/或調優現有應用以發揮最高性能,或爲現有或將來設備構建新應用,瞭解編程模型和高效利用資源之間的相互做用極其關鍵。 以此爲起點,全面瞭解代碼現代化。 關於性能,您的代碼相當重要!編程

構建軟件的並行版本可以使應用在更短的時間內運行指定的數據集,在固定時間內運行多個數據集,或運行非優化軟件禁止運行的大型數據集。 並行化的成功一般經過測量並行版本的加速(相對於串行版本)來進行量化。 除了上述比較以外,將並行版本加速與可能加速的上限進行比較也十分有用。 經過阿姆達爾定律和古斯塔夫森定律能夠解決這一問題。數組

出色的代碼設計將幾個不一樣層面的並行化均考慮在內。緩存

  • 第一層並行化是矢量並行化(代碼內),在大型數據塊上執行相同的計算指令。 代碼的標量部分和並行部分都將受益於高效的矢量計算。
  • 第二層並行化是線程並行化,其主要特色是單個進程的多條合做線程經過共享內存進行通訊,共同處理某項指定任務。
  • 第三層並行化是以獨立合做進程的方式開發多個代碼時,各代碼之間經過消息傳遞系統進行通訊。 這種被稱爲分佈式內存隊列並行化,之因此如此命名,是由於每一個進程指定一個獨有的隊列號。

開發可以高效使用這三層並行化,並具有高性能的代碼是實現代碼現代化的最佳選擇。性能優化

綜合考慮這幾點會對設備的內存模式產生積極的影響:主內存容量與速度、與內存位置相關的內存訪問時間、高速緩存容量與數量,以及內存一致性要求。網絡

矢量並行化時,若是出現數據不對齊,會嚴重影響性能。 數據應以高速緩存友好型方式進行整理。 若是不這樣,當應用請求不在高速緩存內的數據時,性能將會降低。 當所需的數據在高速緩存內,內存訪問速度會達到最快。 高速緩存之間的數據傳輸均以高速緩存行進行,所以,若是下一組數據不在當前高速緩存行內,或分散於多個高速緩存行,應用的高速緩存效率會下降。數據結構

除法和超越數學函數很是昂貴,即便指令集直接支持這些函數。 若是您的應用在運行時代碼內使用多項除法和平方根運算,由於硬件內的功能單元有限,性能會有所下降;鏈接這些單元的管道可能會佔主導。 因爲這些指令很是昂貴,開發人員但願高速緩存使用頻率較高的值,以提高性能。多線程

「一刀切」的技術不存在。 人們太過於依賴正在處理的某個問題和對代碼的長期要求,但優秀的開發人員會關注不一樣層面的優化,不只知足當前須要,還會知足將來需求。架構

英特爾構建了一套完整的工具來協助代碼現代化,包括編譯器、資源庫、調試器、性能分析器,並行優化工具等等。 此外,做爲並行計算機開發領域的領導者,英特爾以其超過三十年的豐富經驗爲基礎提供網絡研討會、文檔、培訓示例,以及最佳方法和案例研究。app

面向多層並行的代碼現代化 5 階段框架

代碼現代化優化框架以系統化方式進行應用性能優化。 該框架將應用分爲 5 個優化階段,各階段相互做用,相互影響,以共同提高應用性能。 可是,啓動優化流程以前,您應考慮應用是否須要從新構建(根據如下指南)以實現最高性能,而後按照代碼現代化優化框架進行優化。

藉助該優化框架,應用可在英特爾® 架構上實現最高性能。 這種分佈式方法有助於開發人員在最短的時間內實現最高的應用性能。 換句話說,它支持程序在執行環境中最大限度地使用全部的並行硬件資源。 這 5 個階段分別爲:

  1. 利用優化工具和庫:使用英特爾® VTune™ Amplifier 分析工做負載,以肯定熱點,並使用英特爾® Advisor XE識別矢量化和線程化機會。 使用英特爾編譯器生成最佳代碼,並在適當的狀況下運用英特爾® 數學核心函數庫英特爾® TBBOpenMP* 等優化的資源庫。
  2. 標量串行優化:保持正確的精度,輸入常量,並使用合適的函數和精度標記。
  3. 矢量化:利用 SIMD 特性以及數據佈局優化。採用高速緩存對齊的數據結構,將結構數組轉化爲數組結構,並最大限度地減小條件邏輯。
  4. 線程並行化:分析線程擴展,並將線程與內核關聯。 擴展問題一般是因爲線程同步或內存利用率低下所形成的。
  5. 將應用從多核擴展到衆核(分佈式內存隊列並行化):擴展對高度並行化應用來講極爲重要。 在將執行對象從一種偏心的英特爾架構(英特爾® 至強™ 處理器)換至另外一種(英特爾® 至強融核™ 協處理器)的過程當中,最大限度地減小變化並最大限度地加強性能。

5 Stages of code modernization

代碼現代化 – 5 階段的實際運用

第 1 階段 在開始優化項目時,您須要選擇一個優化開發環境。 該選擇對於後續步驟具備重要的影響。 它不只會影響您獲得的結果,還能大幅減小您的工做量。正確的優化開發環境能夠爲您提供出色的編譯器工具、現成的優化庫、調試工具和性能評測工具,幫助您準確地查看代碼在運行時正在作什麼。 查看英特爾® Advisor XE工具中的網絡研討會,並以此識別矢量化和線程化機會。

第 2 階段 用盡了可供使用的優化解決方案後,若是還要發揮應用的更高性能,您須要啓動與應用的源代碼相關的優化流程。 在開展活動並行編程以前,您須要確保應用在進行向量化和並行化處理以前可提供正確的結果。 一樣重要的是,您須要確保應用可以以最少的運算獲得正確的結果。 您要考慮數據和算法相關的問題,如:

  • 選擇合適的浮點精度
  • 選擇合適的估算法準確度:多項式或有理數
  • 避免跳躍算法
  • 利用迭代計算縮短循環運算長度
  • 避免或最大程度減小算法中的條件分支
  • 避免重複計算,使用以前的結果

您還必須處理語言相關的性能問題。 若是您使用的是 C/C++,與該語言相關的問題包括:

  • 對全部常量使用外顯式型態法 (explicit typing),以免自動升級
  • 選擇正確的 C 運行時函數類,好比 doubles 或 floats: exp()expf()abs()fabs()
  • 以顯性方式將點別名告知編譯器
  • 顯式調用內聯函數,以免開銷

第 3 階段 嘗試矢量級並行化。 首先嚐試對內層循環進行矢量化。 爲了獲取高效的矢量循環,請確保控制流分散達到最少,以及內存訪問保持一致。 外層循環矢量化是一種用於加強性能的技術。 默認狀況下,編譯器會對嵌套循環結構中最內層的循環進行矢量化處理。 但在某些狀況下,最內層循環中的迭代數量較小。 此時,對最內層循環進行矢量化有些得不償失。 可是,若是外層循環中具備更多的工做,則可使用一個基本函數組合(strip-mining 和編譯指示/指令 SIMD)在外層循環強制執行矢量化操做,以實現更好的效果。

  1. SIMD 在「封包」和對齊的輸入數據上表現最爲出色,但因爲其自己的性質,它會對控制分散形成不利影響。 此外,若是應用實施專一於數據鄰近度,現代硬件會實現出色的 SIMD 和線程性能。
  2. 若是內層循環沒有足夠的工做(例如,運行次數很是低;矢量化的性能優點能夠測量),或數據依賴性妨礙針對內層循環的矢量化,請嘗試對外層循環進行矢量化。 外層循環可能會產生控制流分散;尤爲是在內層循環的運行次數因爲外層循環每一個迭代的不一樣而有差別的狀況下。 這樣會限制經過矢量化而實現的性能改進。 外層循環的內存訪問可能與內層循環不一樣。 這樣會形成收集/分散指令(而非矢量加載和存儲),從而大大限制經過矢量化而實現的擴展。 數據轉換(好比轉置二維數組)可緩解這些問題,或嘗試將結構數組轉化爲數組結構
  3. 因爲循環層級較淺,上述指南可能會形成須要同時對循環進行並行化和矢量化處理。 在這種狀況下,該循環不只須要提供足夠的並行工做以彌補開銷,還要維持控制流均勻性和內存訪問一致性。
  4. 更多詳情請查看矢量化要素

第 4 階段 如今咱們要進行線程級並行化處理。 肯定最外層,並嘗試對該層進行並行化處理。 顯然,這要求維護潛在數據競跑,並在須要時將數據聲明移到循環內部。 它還要求以高效利用高速緩存的方式維護數據,以下降跨多條並行路徑進行數據維護所產生的開銷。 之因此對最外層進行並行化處理,是但願爲每條獨立線程提供儘量多的工做。 阿姆達爾定律代表: 使用多臺處理器的程序在並行計算過程所實現的加速受制於程序順序片斷所需的時間。 因爲工做量須要用來彌補並行化所產生的開銷,所以有利於每條線程擁有儘量多的並行工做。 若是因爲不可避免的數據依賴性致使最外層沒法實現並行化,請嘗試對可以正確實現並行化的下一個最外層進行並行化處理。

  1. 若是最外層的並行工做量可以知足目標硬件的須要,並能隨並行資源的合理增長而進行擴展,那麼您已達到並行化處理的目標。 請勿進行其餘並行化處理,由於這樣會顯著增長開銷(線程控制開銷將否認一切性能改進),也沒法實現任何性能提高。
  2. 若是並行工做仍然不夠,例如,通過內核擴展測試,最多隻能擴展到少許內核,而沒法擴展到實際內核數,請嘗試對其餘層(儘可能爲最外層)進行並行化處理。 請注意,您無需將循環層級擴展到全部可用內核,由於可能有其餘循環層級處於並行執行之中。
  3. 若是沒法在第 2 階段生成可擴展代碼,緣由多是算法中的並行工做不夠。 這表示,劃分多條線程之間的固定工做量使每條線程獲得的工做量極少,所以啓動和終止線程所產生的開銷抵消了有用工做。 也許算法可以進行擴展以處理更多工做,例如,嘗試處理更大的問題。
  4. 請確保您的並行算法可以高效利用高速緩存。 若是不是,請將該其從新設計成高速緩存高效型算法,由於這種算法不隨並行化而擴展。
  5. 更多詳情敬請查看英特爾多線程應用開發指南系列。

第 5 階段 最後咱們要作的是多節點(隊列)並行化。 許多開發人員認爲,消息傳遞接口 (MPI) 就是「僅運行」於場景背後的黑匣子,將數據從一項 MPI 任務傳輸到另外一項。 對於開發人員來講,MPI 的魅力在於其算法編碼獨立於硬件。 而開發人員擔心的是,因爲衆核架構採用 60 多個內核,任務之間的通訊可能會在單個節點內部或跨節點產生通訊風暴。 爲了緩解這些通訊瓶頸,應用可採用混合技術,混合使用幾項 MPI 任務和幾條 OpenMP 線程。

通過良好優化的應用可處理矢量並行化、多線程並行化和多節點(隊列)並行化。 然而,爲了高效完成這些並行化,可以使用標準分佈式方法,以確保兼顧到各階段的層面。 根據個獨立應用的特定需求,能夠(一般)對上述階段進行從新排序;您能夠在某一階段迭代兩次以上,以實現預期性能。

根據咱們的經驗,必須實施全部階段,以確保應用不只可以在目前的可擴展硬件上實現出色性能,還可在將來硬件上進行有效擴展。

試試看!

相關文章
相關標籤/搜索