999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于CUPTI接口的典型GPU程序負載特征分析

2016-07-19 02:14:14翟季冬陳文光
計算機研究與發展 2016年6期

鄭 禎 翟季冬 李 焱 陳文光

(清華大學計算機科學與技術系 北京 100084)(z-zheng14@mails.tsinghua.edu.cn)

?

基于CUPTI接口的典型GPU程序負載特征分析

鄭禎翟季冬李焱陳文光

(清華大學計算機科學與技術系北京100084)(z-zheng14@mails.tsinghua.edu.cn)

摘要基于圖形處理器(graphics processing unit, GPU)加速設備的高性能計算機已經成為目前高性能計算領域的一個重要發展趨勢.然而,在當前的GPU設備上開發高效的并行程序仍然是一件非常復雜的事情.針對這一問題,1)總結了影響GPU程序性能的5類關鍵性能指標;2)采用NVIDIA公司提供的CUPTI底層接口,設計并實現了一套GPU程序性能分析工具集,該工具集可以有效地分析GPU程序的性能行為;3)采用該工具集對著名的GPU評測程序集Rodinia中的17個程序和一個真實應用程序進行了負載特征分析.總結出常見性能瓶頸的典型原因,并給出一些開發高效GPU程序的建議.

關鍵詞圖形處理器;負載特征分析;Rodinia;硬件計數器;性能指標

近年來,基于加速設備的超級計算機已經成為高性能計算領域一個重要發展趨勢.在2014年6月最新發布的超級計算機TOP500排名中,有48個計算機系統使用了GPU加速器.其中,在前15位的超級計算機中有5個計算機使用了GPU加速器.目前,NVIDIA公司的GPU是最主流的GPU加速器,在上述TOP500中有48個使用GPU加速器的超級計算機中,有46個使用的是NVIDIA架構的GPU,其余2個使用了AMD的GPU.

盡管基于加速設備的超級計算機變得越來越流行,但是,在這些系統上編寫高效率的并行程序仍然是一件非常復雜的事情.我們以NVIDIA的GPU設備為例,NVIDIA公司推出的通用編程框架CUDA(compute unified device architecture)是目前應用最為廣泛的編程模型,但編寫高效的CUDA程序非常困難.一方面,GPU設備的存儲器層次結構較為復雜,除了片外的全局存儲器(global memory)、常數存儲器(constant memory)和紋理存儲器(texture memory)之外,GPU還向應用開發人員開放了對片內的共享存儲器(shared memory)的訪問接口,這些存儲器都需要程序員在程序中顯示地進行管理;另一方面,CUDA編程模型本身也提供多層次的程序組織方式,具有網格(grid)、線程塊(thread block)、warp等,不同組織形式下有不同的線程間通信機制和存儲器共享與訪問機制.這些復雜的編程機制導致GPU程序的編寫及優化比較困難.

針對GPU程序性能的瓶頸,目前國內外研究人員提出了很多相關的優化技術.Zhang等人[1]提出了一種軟件的方法在運行時優化GPU程序中控制和訪存的不規則問題,但是目前該工作只支持簡單的訪存行為優化,尚不支持較復雜的程序.Yang等人[2]提出一個基于指導編譯語句的方式優化GPU程序中的嵌套并行.Margiolas等人[3]開發了一個可移植的框架優化OpenCL程序中CPU和GPU之間通信傳輸開銷高的問題.Xiang等人[4]發現在GPU程序中不同warp間會存在顯著的負載不均衡現象,由于目前GPU的warp調度方式會導致GPU資源的顯著浪費,針對上述問題他們提出一種新的資源管理方式,可以有效提高GPU程序性能并降低系統的整體能耗.盡管已有大量的研究工作試圖自動優化GPU程序的各種性能行為,但是,缺少對典型GPU程序的負載特征的詳細分析和總結.

為了有效分析當前典型GPU程序的負載特征,本文首先歸納出GPU程序若干重要性能指標,其中包括計算訪存比、實際浮點性能、帶寬利用率、GPU占用率、共享存儲器訪問效率、全局存儲器訪問效率等.并且,為了有效獲取GPU程序的上述指標,我們采用NVIDIA公司提供的底層CUPTI接口(CUDA profiling tools interface)自主開發了一套性能分析工具,該工具可以在不修改用戶源碼的情況下精確獲取GPU程序上述性能指標.本文采用該工具集對著名的GPU評測程序集Rodinia[5]中17個程序和全球正壓大氣淺水波模式應用程序[6]進行了性能分析,統計了各個程序上述的性能指標,并對部分重要性能指標表現的性能瓶頸進行了程序優化.本文的分析結果對CUDA程序優化及未來GPU體系結構的設計都具有指導意義.

1相關工作

目前已有一些工具可以進行CUDA程序性能分析,但都存在一些不足.PAPI(performance application programming interface)[7]是應用廣泛的程序性能分析工具,提供了針對CUDA程序的性能分析接口.使用PAPI接口在待測試程序代碼中進行插裝,就可以得到CUDA程序的部分硬件計數器值.但如前所述,使用PAPI進行性能測試時需要對源代碼進行修改,這增加了性能測試工作的難度和繁瑣程度;另外,PAPI性能分析接口每次只能夠讀取少量的硬件計數器值,為得到大量硬件計數器值,需要多次修改插樁代碼并多次運行.TAU(tuning and analysis utilities)[8]提供了功能更為強大的CUDA程序性能分析功能.該工具可以追蹤CUDA程序各種庫函數操作的執行時間和具體執行信息(如復制函數復制的字節數等),并能夠在不修改待測試程序源碼的情況下收集程序運行時的硬件計數器指標值.但在CUDA程序的1次運行中,TAU只能夠收集少量的硬件計數器指標值,為了收集較多的指標值,需要手動地多次執行整個程序,使用較為繁瑣;另外,TAU只能收集單純的硬件計數器值,不能收集或計算綜合性能指標,而獨立的硬件計數器值難以直接反映程序的性能特性,這使得其性能分析結果難以引導開發者進行性能優化.Visual Profiler[9]是NVIDIA官方提供的CUDA性能分析工具.該工具提供可視化的操作界面,能夠收集GPU上所有的硬件計數器值,且能夠收集并計算一些綜合性能指標.但該工具對部分重要性能指標默認不做收集,而需要開發者進行指標的選擇,初級CUDA程序開發者難以選擇出重要的性能指標并通過查看眾多性能指標而快速確定程序性能瓶頸.

目前已有一些CUDA程序優化方法的研究.Yang等人[10]的工作中通過對10個開源CUDA程序的分析,總結了若干種導致程序性能低下的程序模式,并通過實驗證明對這些程序模式的優化能夠顯著提高程序性能.Stratton等人[11]的工作中描述了對CUDA程序優化有關鍵作用的方法,包括數據存儲方式的轉換、合并訪問、負載均衡化、控制并行粒度等方法,這些優化模式應用在CUDA程序上有普遍的性能提高.Yang等人[12]的工作中提出了一個源到源的CUDA程序自動優化工具,其中采用的優化方法包括向量化,全局內存合并訪問,線程合并以及數據預取等方法.在Li等人[13]以及Chen等人[14]的工作中,研究了變量存儲位置轉換的問題.Li等人[13]的工作主要涉及到全局內存和共享內存變量轉換為寄存器變量,以及共享內存變量轉換為全局內存變量這幾個方面;Chen等人[14]的工作則側重于將全局內存變量轉變為其他類型變量,結果顯示通過內存變量位置的合理轉換,程序性能能夠得到很大的提升.Wahib等人[15]的工作中,提出了通過合并核函數的方式進行數據重用的方法,被合并的核函數需要有共同的參數,此時這些參數的訪問能夠被重用,實驗顯示該方法對部分程序有很好的優化效果.李建江等人[16]提出了一種將單GPU程序轉化為多GPU程序的方法,通過該轉化能夠使大型程序運行在多GPU上,取得更好的加速效果.這些針對CUDA程序的研究都取得了一定的效果,但這些研究都側重于以具體的方法對某一類程序進行優化,并沒有對普通程序進行性能瓶頸分析和定位.

對常用CUDA程序做負載分析的相關工作較少.Che等人[5]的工作中,對基準測試程序套件Rodinia進行了多樣性分析,說明了Rodinia中程序能夠較為廣泛地覆蓋并行程序的特性,并分析了影響CUDA程序性能的一些問題,但該工作中并沒有研究反映CUDA程序性能特性的性能指標,也沒有針對CUDA重要性能特性對Rodinia做負載特征分析;同時,該工作中只是對一套基準測試程序套件進行分析,沒有對真實應用程序進行性能分析.

目前已有一些針對CUDA程序的部分特性進行性能建模的工作.在Williams等人[17]提出的Roofline模型中,分析了實測浮點性能與理論浮點性能峰值、帶寬峰值及操作密度的函數關系.該模型中,操作密度是指單位字節的內存數據傳輸之下的操作數量,為操作數量與訪存數量的比值,對于給定的操作密度,通過該模型可以確定程序是計算受限還是訪存受限.本論文中借鑒了該工作的方法,確立了計算訪存行為的性能指標.

2CUDA程序性能指標

為了有效地分析CUDA程序的負載特征,明確程序的性能瓶頸,本文提出5類關鍵性能指標描述CUDA程序的性能行為:

1) 計算訪存行為(計算訪存比、實測浮點性能和帶寬利用率)

計算訪存比對于確定程序的類型以及檢測程序性能受限因素有重要作用:①對基準測試程序進行計算訪存比測試可以統計出通用程序的計算訪存特征;②對于單個程序,綜合計算訪存比、GPU帶寬與帶寬利用率以及理論浮點性能峰值與實測浮點性能可以看出程序是訪存受限還是計算受限[17].科學計算中,大部分計算指令為浮點型指令,而通常影響程序性能的訪存方式主要是全局存儲器訪問,因此,統計浮點計算指令與全局存儲器訪存比更有意義.

我們定義浮點計算與全局訪存比為浮點指令的條數與全局存儲器訪問字節數的比率,記為Rf-g,記浮點指令條數為If,核函數執行時間為Dk,單位時間內全局存儲器的讀與寫的字節數分別為Tgld與Tgst,則有:

(1)

由于我們收集的Tgld與Tgst為運行時的指標,最終得到的全局存儲器訪問字節數也是實際值,而非理論值在作分析時,理論的存儲器訪問量與實際值可能會有偏差.

GPU實測浮點性能Pf-achieved是指GPU每秒實際執行的浮點運算次數,浮點計算單元利用率Uf是指實測浮點性能與理論峰值Pf-peak的比率.這2個指標能夠反映出程序的浮點計算量及浮點計算單元的利用情況,其計算方法為

(2)

(3)

GPU帶寬利用率Udram可以通過指標Tdramread,Tdramwrite以及GPU的帶寬B求得,其中Tdramread和Tdramwrite分別表示單位時間內GPU設備上內存讀寫字節數.Udram能夠綜合地反映程序對存儲器訪問的效率,其計算方法為

(4)

2) GPU占用率

GPU占用率(occupancy)是指實際運行的warp占最大理論warp數量的比值,包括理論GPU占用率和實際GPU占用率.影響理論GPU占用率的指標有3個:每個線程塊中線程的數量、每個線程占用的寄存器數量和每個線程塊分配的共享存儲大小.實際GPU占用率由CUPTI中定義的achieved_occupancy來表示,該值受到每個網格中線程塊數量及實際運行環境的影響,需要在程序運行時通過CUPTI相關函數獲取.

GPU占用率反映了程序實際開啟的并行計算線程數量占理論最大數量的比例,一般來說,比值越大表示程序對GPU資源的利用率越高,并行度越好.一方面,GPU占用率受開發者配置的并行線程數量的影響,開發者配置的線程數過少時GPU占用率會較低;另一方面,GPU占用率受單位線程占用的存儲器資源數量的影響,當每個線程中局部變量較多從而占用較多寄存器時,或者每個線程塊占用的共享內存數量較多時,會因為存儲器資源不足而無法發起太多線程,導致GPU占用率較低.GPU占用率可以反映程序在這2方面的特性.

對于訪存受限的CUDA程序,當其并行度較高時,大量的線程并行執行通常能夠有效地掩蓋數據傳輸帶來的時延,從而提高程序性能.因此GPU占用率是反映訪存受限的CUDA程序性能的重要指標.但對于計算密集型程序,單純提高GPU占用率并不能很有效地提高程序性能.

3) 共享存儲器訪問效率

反映共享存儲器訪問效率的指標是shared_efficiency,表示對共享存儲器數據訪問的請求數據量與實際數據量的比率,其值越大表示共享存儲器訪問效率越高.

在共享內存的最佳訪問狀態下,每個half-warp中不同線程訪問到不同的bank中(或所有線程訪問同一地址),此時各個線程能夠同時訪問共享內存,shared_efficiency=1.0;當存在bank沖突時,不同線程訪問到同一個bank時會使得各線程只能依次訪問,此時shared_efficiency降低.因此,shared_efficiency能夠反映出共享存儲器使用中的bank沖突(bank conflict),當該指標值較低時,往往表示存在bank沖突.

4) 全局存儲器訪問效率

反映全局存儲器訪問效率的指標是gld_efficiency和gst_efficiency.gld_efficiency的含義是對全局存儲器數據讀取的請求數據量與實際數據量的比率,其值越大表示讀取數值的效率越高,該比率可能小于1.0,可能等于1.0,也可能大于1.0.gst_efficiency表示對全局存儲器數據寫入的請求數據量與實際數據量的比率,與gld_efficiency的意義類似,值越大表示效率越高.

全局內存的最佳讀取方式是多個線程讀取同一地址,此時多個線程只需一次全局內存讀取,gld_efficiency>1.0;當同一個half-warp中的線程對全局內存的讀取地址連續且滿足一定的地址對齊規則時(不同GPU架構下對齊要求不同),該half-warp中各線程對全局內存的讀取能夠合并為同一條讀取指令,此時gld_efficiency=1.0;當half-warp中不同線程對全局內存變量的訪問不連續或不滿足地址對齊規則時,不同線程需多次讀取全局內存,而CUDA中對全局內存讀取時是以32 B,64 B或128 B為單位的,單次讀取單個變量時會讀入大量不需要的內存,gld_efficiency<1.0.對于全局內存的寫入和gst_efficiency有類似的結論.

gld_efficiency和gst_efficiency可以有效地檢測出非合并訪問(uncoalesced access),對于測試CUDA程序全局存儲器訪問效率很有效.

5) 線程束執行效率

線程束執行效率主要由線程分歧的情況來反映.對于CUDA核函數,當分支條件控制指令數不大于某個閾值時,編譯器會使用帶有謂詞的指令替換分支指令,各個線程會根據控制條件將各條替換過的分支指令與設置為true或false的謂詞相關聯,此時每一條分支指令都會在任何一個線程中發射,但最終只有謂詞為true的指令才會被實際執行;當分支數大于閾值時,編譯器不會進行分支謂詞替換,此時同一half-warp中執行不同分支的線程無法并行執行,會出現一部分線程等待其他線程的情況.

能夠反映核函數執行過程中線程分歧的指標是warp_execution_efficiency和warp_nonpred_execution_efficiency.warp_execution_efficiency是指在流處理器中各個warp中實際運行的線程數量占最大理論線程數量的比值的平均值,該值為1.0時表示不考慮分支謂詞替換分支指令的情況下沒有線程分歧,否則一定有線程分歧.warp_nonpred_execution_efficiency是指在一個流處理器上各個warp中執行非分支預測指令的線程數量占最大理論線程數量的比值的平均值,該值為1.0時表示沒有使用分支謂詞替換分支指令,否則存在分支預測.綜合2個指標可以全面地了解核函數中的線程分歧情況.

通過上述指標的分析,可以清楚地了解CUDA程序的計算特征、訪存特征以及GPU特有的性能行為,例如,線程分歧和共享內存使用情況.下面介紹本文如何通過GPU的CUPTI接口獲取上述性能指標.

3性能工具的實現

本文設計并實現的性能分析工具能夠在待測試程序運行時收集第2節討論的重要性能指標,使用該工具時無需修改待測試程序源碼.為實現該工具,我們對CUDA運行時庫函數進行了插樁,重寫了部分關鍵的庫函數,并通過設置LD_PRELOAD環境變量使得CUDA程序在調用庫函數時鏈接并執行我們重新實現的版本,進而在執行時運行采集性能指標的程序段.對庫函數插樁前后核函數執行流程如圖1所示:

Fig. 1 The processes of the kernel before and after instrumentation.圖1 對庫函數插樁前后核函數執行流程

我們在插入的代碼中使用CUPTI接口[18]來收集CUDA程序的性能指標,CUPTI可以收集的指標主要包括程序運行信息、事件和CUPTI定義的Metric三類.其中,事件指GPU的硬件計數器值,而Metric則是由若干個事件值計算出的綜合性指標.在第3節中描述的重要性能指標大部分可以直接由Metric來表示,另外一部分可以通過其他Metric求出,因此我們的目標是收集需要的事件值,進而得到重要的Metric值.

為得到需要的重要Metric值而必須首先得到較多的事件值,而由于硬件計數器數量限制,每次核函數運行時可以收集到的事件值數量有限,因此需要多次執行核函數,分多次收集事件值.為此,我們通過對庫函數插樁而改變了核函數的發射過程,使得原先一次執行的核函數被多次發射,從而在每次執行時求得一部分硬件計數器值,最終求出所有需要的性能指標值.通過這樣的方式,核函數被多次執行,而整個程序則仍然只需要執行一次,且整個過程對使用者來說是透明的.核函數發射的控制函數主要是cudaConfigureCall,cudaSetupArgument,cudaLaunch,前兩者將核函數配置參數與運行參數壓入棧中,后者發射核函數,編譯時源程序中核函數調用語句會被這3個函數所替代.本文實現的性能分析工具重新實現了這3個函數,在前兩者中備份了函數參數,在新的cudaLaunch中多次調用原函數cudaLaunch,從而實現核函數的多次執行,每次調用后收集若干事件值,在收集到所有所需事件值后得到所需的各個Metric值.為了保證多次調用核函數后程序的正確性,需要在每次調用cudaLaunch前恢復部分變量值為進入核函數時的初始值,并重新讀取備份的函數參數.

通過修改庫函數將原先核函數的每次執行變為多次執行后,如不恢復變量值為進入核函數時的初始值,則可能導致程序的錯誤,因為核函數執行過程中可能修改部分全局內存變量的值,此時原先只執行一次的核函數被修改為多次執行后會導致部分全局內存變量被累計修改多次,從而導致錯誤.為了避免這樣的錯誤,需要提前備份可能被修改的變量的值,并在每次重復調用cudaLaunch前將上次執行時被改變的變量恢復為正確的初始值,從而使核函數的多次執行是在同樣的初始條件之下進行,在最后一次重復調用cudaLaunch之后更新變量備份值.需要備份的變量為作用域大于核函數作用域且在核函數中可以被改變的變量,滿足此條件的變量只有全局存儲器變量,為了保證所有可能被改變的全局存儲器變量都被備份,我們備份了程序中所有的全局存儲器變量,并通過對相應庫函數進行插樁而實現了備份值跟隨原變量值的同步更新.為了實現變量的備份與同步更新,性能工具實現時維護了一個鏈表,鏈表中每個節點對應于一個全局內存變量,節點保存了被備份變量的內存地址及備份值.我們重新實現了cudaMalloc等庫函數,每當通過這些函數新創建一個全局內存變量時在鏈表中增加1個節點,從而保證備份所有的全局內存變量,同時,我們重新實現了cudaMemcpy等函數,每當通過這些函數改變內存變量值時,根據內存變量地址找到對應的備份節點,同步更新節點的備份值,從而實現備份值的同步更新.在每次重復調用cudaLaunch前恢復全部全局內存變量值的方法為:遍歷備份鏈表,將各節點指向的內存地址的內存值恢復為節點存儲的備份值;最后一次重復調用cudaLaunch后,則以類似方法將鏈表中各個節點的備份值更新為對應變量的當前值.

最后,我們對該工具的有效性與正確性進行了驗證.該工具收集的部分指標與Visual Profiler一致,對于該部分指標,我們將該工具與Visual Profiler的輸出結果進行了對比,結果顯示兩者沒有明顯差異;對于在Visual Profiler中沒有的指標,其中間結果都可以由Visual Profiler進行收集,我們驗證了這些指標的中間結果的正確性,最后通過對CUDA官方示例中部分程序的源碼及運行結果進行分析而驗證了這些指標的有效性與正確性.

4CUDA程序負載特征分析

本文對著名的CUDA評測程序Rodinia中17個程序和全球正壓大氣淺水波方程求解應用程序采用上述性能指標進行分析.本文的實驗平臺為Dell Precision T5600服務器,CPU型號為Intel Xeon E5-2620,內存大小為64 GB,操作系統為Red Hat Enterprise Linux 6.4 Server,GPU型號為NVIDIA Tesla K20c,該GPU的CUDA計算核心數量為2 496個,共享內存大小為4 800 MB.實驗中使用的CUDA版本為CUDA 6.0.

Rodinia中程序能夠較為廣泛地覆蓋并行程序的特性,其CUDA版本覆蓋了CUDA程序的多方面特性,因此其成為了對CUDA程序進行測試分析的重要程序集.本文分析的Rodinia中17個程序如表1所示:

Table 1 Programs in Rodinia

4.1Rodinia負載分析

1) 計算訪存分析結果

Rodinia中17個程序的浮點計算與全局內存訪問比如圖2所示,可以看出,37個核函數中有9個函數該指標值大于1,其中有4個函數該指標值大于2,有2個函數該指標值大于3,分別是LV程序的核函數(7.97)和KM的函數kmeansPoint(86.25).部分程序的浮點計算訪存比為0,該類程序中沒有浮點計算.

Fig. 2 The Rf-gvalues of the 17 programs in Rodinia.圖2 Rodinia中17個程序浮點計算與全局內存訪問比

本文中分析的應用程序為求解全球正壓大氣淺水波方程的程序,該方程為大氣模擬過程中最基礎、最重要的方程.該程序支持多種混合架構,我們選取其單GPU版本進行了性能分析.

17個程序的浮點計算單元利用率如圖3所示,可以看出,這17個程序的浮點計算單元利用率普遍很低,37個核函數中有36個的該指標值小于0.04,且其中28個核函數該值小于0.01;LV程序的核函數該指標值最高,但也只達到0.177.這說明17個程序對浮點計算單元的利用率普遍較低.

Fig. 3 The Ufvalues of the 17 programs in Rodinia.圖3 Rodinia中17個程序的浮點計算單元利用率

17個程序的帶寬利用率Udram指標值如圖4所示,可以看到,在37個核函數中有28個核函數的帶寬利用率小于0.5;CFD的函數cuda_time_step的該值最高,為0.7267.程序帶寬利用率整體不夠高的原因可能有2個:①程序本身的特性,部分程序由于算法本身的特性及程序規模等原因,使得其即使訪存方式達到最優也無法太多地利用帶寬;②程序本身訪存方式設計不夠合理,導致帶寬利用率較低.另外,與浮點計算單元利用率相比,程序的帶寬利用率整體高于前者.

Fig. 4 The Udramvalues of the 17 programs in Rodinia.圖4 Rodinia中17個程序的帶寬利用率指標值

Fig. 5 The achieved_occupancy values of the 17 programs in Rodinia.圖5 Rodinia中17個程序各核函數的實際occupancy值

從以上分析可知,Rodinia中程序的浮點計算單元利用率普遍較低,程序帶寬利用率普遍優于浮點計算單元利用率.同時,多數程序的浮點計算與全局內存訪問比較低,說明程序的全局內存訪問量相對浮點運算而言更多,這與帶寬利用率相對略高而浮點計算單元利用率低的趨勢是一致的.由此可見,程序的帶寬利用率與浮點計算單元利用率一定程度上受程序本身計算訪存數量特征的影響.

2) occupancy分析結果

Rodinia中17個程序的occupancy如圖5所示,在37個核函數中有22個達到了0.7,其他15個核函數的occupancy值較小,其中GS程序的函數Fan2、LUD程序的函數lud_perimeter與lud_diagonal、MC程序的核函數kernel值最低,都為0.2,其理論occupancy值也較低,為0.25.

對于GS程序的函數Fan2,在輸入為1 024×1 024的矩陣的情況下,程序網格的維數為(256,256,1),線程塊維數為(4,4,1),由此可見,線程塊維數較小最可能是導致occupancy值較低的原因.修改代碼,將線程塊維數設置為(16,16,1),測試結果顯示實際occupancy值提升為0.86.

修改程序前后測試信息如表2所示,可以看出增大線程塊維數進而增大occupancy值能夠有效地減少核函數執行時間(減小了0.56).同時,在采用此方法增大occupancy之后,程序的全局存儲器訪問效率有所降低(gld_efficiency與gst_efficiency值減小),這說明在增大occupancy之后,程序中同時運行的warp更多,程序并行性更高,高并行性使得訪存時延被大量的計算指令的執行有效地掩蓋了.

Table 2 Optimization Result of Fan2 Function in GS Program

Fig. 6 The shared_efficiency values of the 17 programs in Rodinia (0 means no use of shared memory).圖6 Rodinia中17個程序各核函數的shared_efficiency值(值為0表示沒有使用共享內存)

3) shared_efficiency分析結果

Rodinia中17個程序的shared_efficiency值如圖6所示,在37個核函數中有14個使用了共享存儲器,在這14個函數中有8個程序的shared_efficiency指標值達到了1.0,2個程序的shared_efficiency指標值達到了0.8,其他4個函數的shared_efficiency指標值較小,其中LV程序的函數kernel_gpu_cuda有最低的利用率,為0.4211.

圖7顯示了LV程序的函數kernel_gpu_cuda在使用共享內存時存在bank沖突.該函數中定義了2個共享內存數組rA_shared和rB_shared,數組元素都是結構體,大小為32 B.在計算能力為3.5的GPU中,共享存儲器被分為32個bank,該程序運行時bank的存儲單元大小為4 B,則每訪問連續的32個4 B后會回到原先訪問的bank中.由此可知,該程序中同一個warp中對2個共享內存數組的第n個元素的訪問與第n+4個元素的訪問會產生bank沖突.對于數組rA_shared,warp中不同的線程之間會產生大量的bank沖突;對于數組rB_shared,由在循環中訪問的過程中,half-warp的不同線程可能訪問到相同的bank中,從而造成bank conflict沖突.

4) 全局存儲器訪問效率分析結果

Rodinia中17個程序的gld_efficiency與gst_efficiency值如圖8所示.對于gld_efficiency,MM程序的函數mummergpuKernel有最低值0.032,PT程序的函數find_index_kernel有最高值7.3438;對于gst_efficiency,MM程序的函數printKernel有最低值0.0938,CFD的函數cuda_time_step及其他程序的部分函數有最高值1.0.

Fig. 7 The bank conflict for function kernel_gpu_cuda in program LV accessing rA_shared.圖7 LV程序函數kernel_gpu_cuda訪問變量rA_shared時的bank沖突

Fig. 8 The gld_efficiency and gst_efficiency values of the 17 programs in Rodinia.圖8 Rodinia中17個程序各核函數的全局存儲器訪問效率

如圖9所示,MM程序的函數mummergpu-Kernel中對全局內存的訪問存在非合并訪問的現象.在同一個線程中,對全局內存數組多次以比較隨機的索引值進行訪問,warp中的不同線程對該數組的訪問的位置也很難連續,因此無法合并訪問.最終該函數的gld_efficiency=0.032.

對于PT程序的函數find_index_kernel,其對全局內存塊arrayX和arrayY的訪問一般是連續多次訪問同一個地址,這種情況下warp在執行訪存指令時可以只進行一次訪存,訪存效率較高,gld_efficiency=7.3438.

圖10為MM程序的函數printKernel中部分代碼結構,該函數中存在大量對結構體類型的全局內存數組元素的成員的訪問,訪問的地址難以滿足合并訪問所要求的對齊規則,且warp中各個線程訪問的地址可能不連續,使得出現大量非連續訪問,gst_efficiency值較低,gst_efficiency=0.0938.

在CFD的cuda_time_step等函數及其他程序的部分函數中,對同一warp中對全局內存的訪問是連續的并且是對齊的,因此訪問效率很高,gst_efficiency=1.0.

5) warp執行效率分析結果

Rodinia中17個程序的warp執行效率值如圖11所示,圖11中包括2項指標:warp_execution_efficiency與warp_nonpred_execution_efficiency.可以看到,在37個核函數中,大部分函數的warp執行效率指標值達到或接近0.8,只有少數函數的指標值較低,同時可以看到大部分核函數中,warp_execution_efficiency值都會略大于warp_nonpred_execution_efficiency值,說明在大部分核函數中都存在分支指令的謂詞替換.

MC程序中函數kernel的warp執行效率值最低,warp_execution_efficiency=0.0344,warp_non-pred_execution_efficienc=0.0328.如圖12所示,MC程序的kernel運行時只使用了2個warp,而每個warp中只有一個線程在執行串行程序,其他31個線程空閑,從而使線程分歧比較嚴重,線程利用率非常低.

Fig. 9 The analysis of the performance bottleneck of function mummergpuKernel in program MM.圖9 MM程序的函數mummergpuKernel性能瓶頸分析

Fig. 10 The analysis of the performance bottleneck of function printKernel in program MM.圖10 MM程序的函數printKernel性能瓶頸分析

Fig. 11 The warp execution efficiency of the 17 programs in Rodinia.圖11 Rodinia中17個程序各核函數的warp執行效率

Fig. 12 The analysis of the performance bottleneck of function kernel in program MC.圖12 MC程序的函數kernel性能瓶頸分析

LUD程序的函數lud_internal不存在分支指令,warp中所有線程執行路徑一致,因此不存在線程分歧,warp執行效率最高,warp_execution_efficiency和warp_nonpred_execution_efficiency值都為1.0.

4.2應用程序分析

求解全球正壓大氣淺水波方程的程序分為使用共享內存的版本和不使用共享內存的版本,我們對使用共享內存的版本做了分析,分析結果如表3所示:

Table 3 The Analysis Result of The Cubed-sphere Shallow-water Model Program

該程序浮點計算與全局內存訪問比較高,分析代碼可知,程序計算指令比較多且大多數訪存是針對的共享存儲器,從而有比較高的浮點計算與全局內存訪問比值.程序的實測浮點性能與浮點計算單元利用率比較低,而帶寬利用率較高,因此,優化時需要重點針對計算指令進行.

程序的GPU占用率指標值較低,分析代碼可知,程序中使用了大量的共享內存(每個線程使用40.5 KB共享內存),且大量的局部變量占用了大量的寄存器(每個線程使用63個寄存器),從而使程序無法同時執行太多的線程,導致并行度不夠高.優化時,可以將局部變量和共享內存中的常量存儲于常數存儲器中或使用宏定義來代替,以減少對共享內存和寄存器的使用.

程序的共享內存訪問效率比較低,存在bank沖突.優化時需要改變共享內存數組的組織與訪問形式,消除bank沖突.程序的全局內存訪問效率很高,說明很好地利用了合并訪問的機制;程序線程束執行效率很高,不存在大量的影響性能的條件分支.

總體來說,程序應該從計算指令吞吐率、GPU占用率、共享內存數據結構設計和訪問方式3個方面來進行優化.

5CUDA程序性能建議

根據對Rodinia和淺水波應用程序的負載分析,本文總結出CUDA程序的性能建議:

1) GPU占用率(occupancy)是反映程序性能的重要指標,能夠反映出程序對GPU并行計算單元的利用情況,該值較低表示程序對GPU并行計算單元的利用率較低.影響程序occupancy的指標包括線程塊中線程數量、線程占用的寄存器數量和線程塊分配的共享存儲大小,其中,線程數量反映開發者分配的最大并行線程量,寄存器數量和共享存儲大小反映單位線程占用的存儲器資源大小.在開發CUDA程序時,一方面要盡量減少核函數中局部變量的數量,以減少對寄存器的占用,同時控制共享內存的占用,通過減少單位線程占用的資源量來增大可以同時發起的線程數量;另一方面,在寄存器和共享內存占用量足夠的情況下,按照程序輸入規模盡量多地開啟并行執行的線程.

2) 共享存儲器訪問效率(shared_efficiency)反映的是程序中共享內存的使用效率,能夠反映程序的bank沖突,該值低于1.0時表示存在bank沖突.不同的GPU架構之下,共享內存會被分為16或32個bank,bank的存儲單位大小為4 B或8 B.使用共享存儲器時,需要根據變量所占存儲空間大小進行控制,盡量使half-warp中的不同線程不訪問同一個bank(除非是訪問同一個變量).計算能力不小于2.x的GPU的bank數量為32,這是目前主流的GPU結構.對于這其中bank大小為4 B的GPU,共享內存數組元素存儲大小不大于8 B時,在每個線程只訪問一個元素的情況下各線程連續訪問時恰好不會發生bank沖突;大于8 B時可能發生bank沖突,典型地,當數組元素為8 B的2倍及以上的整數倍時會發生bank沖突,由此可知數組元素為基本變量類型時一般不會發生bank沖突,數組元素為存儲大小較大的結構體時容易發生bank沖突,bank大小為8 B的GPU在以上情況下發生bank沖突的數組元素存儲大小為以上對應大小的倍數.開發者使用共享內存時需要注意以上規律.

3) 全局存儲器訪問效率(gld_efficiency和gst_efficiency)反映程序中全局內存的訪問效率,對應值較小時表示全局內存訪問模式或訪問時對齊方式沒有達到最優.全局內存的合并訪問機制大大提高了其訪問效率,合并訪問對于訪問方式有一定的要求,不同的GPU架構之下其要求不盡相同,但都是針對訪問地址的連續和對齊2方面.全局內存訪問的典型不合理模式包括:依次連續訪問元素類型為結構體的數組中結構體元素的同一個成員,進而導致訪問地址不連續;條件控制語句中根據變化的條件訪問全局內存,導致訪問地址的離散化.全局內存訪問相對較慢,可以使用其他類型存儲器來代替全局存儲器以加速數據訪問速度,對于常量可以使用常數存儲器存儲,對于需要多次訪問的大量數據則可以存儲于共享內存中;對于由于數據量過大等原因而無法存儲于其他存儲器的全局內存變量,對其訪問時盡量使訪問地址連續,盡量不要使用結構體數組的數據結構形式,該數據結構形式下很容易使內存訪問地址離散化,也要盡量避免在條件控制語句中出現的離散訪問;同時,對于不同的GPU架構,需要注意對全局內存數據訪問的對齊方式,以充分利用合并訪問特性進行訪存加速.

4) 線程束執行效率(warp_execution_efficiency與warp_nonpred_execution_efficiency)反映了程序的線程分歧情況,前者沒有考慮分支預測,后者反映分支預測的情況,綜合2個指標可以全面了解線程分歧情況.線程分歧會導致大量線程等待或執行無效指令,對程序性能影響很大,程序開發者應盡量減少控制語句的使用,使用一些方法將控制語句轉化為非控制語句;對于無法避免的控制語句,盡量使其分支以half-warp來劃分,使得同一個half-warp中執行同一個分支,從而避免線程分歧.

6結論

本文中,我們分析總結了CUDA程序的重要性能指標,基于CUPTI接口開發了能夠獲取這些性能指標的性能分析工具,使用該工具對Rodinia中的程序進行了負載分析,并對主要性能指標顯示的部分程序的性能瓶頸在源代碼中進行了原因分析,之后對全球正壓大氣淺水波模式應用程序進行了性能分析,討論了其性能特性.對Rodinia的負載分析結果較全面地反映了常用CUDA程序在各方面的負載特征,該結果可以為未來CUDA程序優化分析及GPU系統結構優化分析提供數據資料.通過對重要性能指標反映有性能瓶頸的部分程序進行分析,我們為開發者展示了常見性能瓶頸的典型原因,并提出了一些開發高效程序的建議.

參考文獻

[1]Zhang E Z, Jiang Y, Guo Z, et al. On-the-fly elimination of dynamic irregularities for GPU computing[J]. ACM SIGPLAN Notices, 2011, 46(1): 369-380

[2]Yang Y, Zhou H. CUDA-NP: Realizing nested thread-level parallelism in GPGPU applications[J]. Journal of Computer Science and Technology, 2015, 30(1): 93-106

[3]Margiolas C, O’Boyle M F P. Portable and transparent host-device communication optimization for GPGPU environments[C] //Proc of Annual IEEE/ACM Int Symp on Code Generation and Optimization. New York: ACM, 2014: 55-65

[4]Xiang P, Yang Y, Zhou H. Warp-level divergence in GPUs: Characterization, impact, and mitigation[C] //Proc of the 20th Int Symp on High Performance Computer Architecture (HPCA). Los Alamitos, CA: IEEE Computer Society, 2014: 284-295[5]Che S, Boyer M, Meng J, et al. Rodinia: A benchmark suite for heterogeneous computing[C] //Proc of IEEE Int Symp on Workload Characterization. Piscataway, NJ: IEEE, 2009: 44-54

[6]Yang C, Xue W, Fu H, et al. A peta-scalable CPU-GPU algorithm for global atmospheric simulations[J]. ACM SIGPLAN Notices, 2013, 48(8): 1-11

[7]Browne S, Dongarra J, Garner N, et al. A portable programming interface for performance evaluation on modern processors[J]. International Journal of High Performance Computing Applications, 2000, 14(3): 189-204

[8]Shende S S, Malony A D. The TAU parallel performance system[J]. International Journal of High Performance Computing Applications, 2006, 20(2): 287-311

[9]NVIDIA Corporation. NVIDIA visual profiler[CP/OL]. 2014 [2014-07-15]. https://developer.nvidia.com/nvidia-visual-profiler

[10]Yang Y, Xiang P, Mantor M, et al. Fixing performance bugs: An empirical study of open-source GPGPU programs[C] //Proc of the 41st Int Conf on Parallel Processing (ICPP). Piscataway, NJ: IEEE, 2012: 329-339

[11]Stratton J A, Anssari N, Rodrigues C, et al. Optimization and architecture effects on GPU computing workload performance[C] //Proc of Innovative Parallel Computing. Piscataway, NJ: IEEE, 2012: 1-10

[12]Yang Y, Xiang P, Kong J, et al. A unified optimizing compiler framework for different GPGPU architectures[J]. ACM Trans on Architecture and Code Optimization, 2012, 9(2): 970-983

[13]Li C, Yang Y, Lin Z, et al. Automatic data placement into GPU on-chip memory resources[C] //Proc of IEEE/ACM Int Symp on Code Generation and Optimization (CGO). Piscataway, NJ: IEEE, 2015: 23-33

[14]Chen G, Wu B, Li D, et al. PORPLE: An extensible optimizer for portable data placement on GPU[C] //Proc of the 47th Annual IEEE/ACM Int Symp on Microarchitecture (MICRO). Piscataway, NJ: IEEE, 2014: 88-100

[15]Wahib M, Maruyama N. Scalable kernel fusion for memory-bound GPU applications[C] //Proc of the Int Conf for High Performance Computing, Networking, Storage and Analysis. Piscataway, NJ: IEEE, 2014: 191-202

[16]Li Jianjiang, Li Xinggang, Lu Chuan, et al. A template technology for transplanting from single-GPU programs to multi-GPU programs[J]. Journal of Computer Research and Development, 2010, 47(12): 2185-2191 (in Chinese)(李建江, 李興鋼, 路川, 等. 一種單 GPU 程序向多GPU移植的模板化技術[J]. 計算機研究與發展, 2010, 47(12): 2185-2191)

[17]Williams S, Waterman A, Patterson D. Roofline: An insightful visual performance model for multicore architectures[J]. Communications of the ACM, 2009, 52(4): 65-76

Zheng Zhen, born in 1991. PhD candidate. His main research interests include high performance computing.

Zhai Jidong, born in 1981. PhD and assistant professor. His main research interests include high performance computing and performance evaluation.

Li Yan, born in 1985. PhD. His main research interests include high performance computing and parallel computing.

Chen Wenguang, born in 1972. PhD and professor. His main research interests include high performance computing and compiler optimization.

Workload Analysis for Typical GPU Programs Using CUPTI Interface

Zheng Zhen, Zhai Jidong, Li Yan, and Chen Wenguang

(DepartmentofComputerScienceandTechnology,TsinghuaUniversity,Beijing100084)

AbstractGPU-based high performance computers have become an important trend in the area of high performance computing. However, developing efficient parallel programs on current GPU devices is very complex because of the complex memory hierarchy and thread hierarchy. To address this problem, we summarize five kinds of key metrics that reflect the performance of programs according to the hardware and software architecture. Then we design and implement a performance analysis tool based on underlying CUPTI interfaces provided by NVIDIA, which can collect key metrics automatically without modifying the source code. The tool can analyze the performance behaviors of GPU programs effectively with very little impact on the execution of programs. Finally, we analyze 17 programs in Rodinia benchmark, which is a famous benchmark for GPU programs, and a real application using our tool. By analyzing the value of key metrics, we find the performance bottlenecks of each program and map the bottlenecks back to source code. These analysis results can be used to guide the optimization of CUDA programs and GPU architecture. Result shows that most bottlenecks come from inefficient memory access, and include unreasonable global memory and shared memory access pattern, and low concurrency for these programs. We summarize the common reasons for typical performance bottlenecks and give some high-level suggestions for developing efficient GPU programs.

Key wordsgraphics processing unit (GPU); workload analysis; Rodinia; performance counter; performance metric

收稿日期:2014-12-10;修回日期:2015-08-11

基金項目:國家自然科學基金項目(61103021);國家“八六三”高技術研究發展計劃基金項目(2012AA010901)

中圖法分類號TP338.4

This work was supported by the National Natural Science Foundation of China (61103021) and the National High Technology Research and Development Program of China (863 Program) (2012AA010901).

主站蜘蛛池模板: 色综合久久综合网| 亚洲美女一区| 国产精品漂亮美女在线观看| AV片亚洲国产男人的天堂| 熟妇无码人妻| 国产sm重味一区二区三区| 一区二区三区国产| 亚洲无码视频喷水| 91视频99| 青青青视频91在线 | 亚洲成人在线网| 91人人妻人人做人人爽男同| 国产午夜一级淫片| 国产成人精品高清在线| 97精品国产高清久久久久蜜芽| 99成人在线观看| 人妻无码AⅤ中文字| 99草精品视频| 国产欧美中文字幕| 97青草最新免费精品视频| P尤物久久99国产综合精品| 四虎在线观看视频高清无码| 老色鬼欧美精品| 中文纯内无码H| 久久青草热| 欧美人在线一区二区三区| 午夜a级毛片| 欧美亚洲国产日韩电影在线| 国产免费精彩视频| 在线亚洲天堂| 2020国产在线视精品在| 中国黄色一级视频| jizz在线免费播放| av一区二区三区在线观看| 国产成人91精品| 在线播放精品一区二区啪视频| 免费一级成人毛片| 午夜一级做a爰片久久毛片| 69视频国产| 内射人妻无码色AV天堂| 亚洲欧美日韩中文字幕在线| 欧美成人精品一级在线观看| 日本91在线| 波多野结衣国产精品| 国产精品香蕉在线观看不卡| 六月婷婷精品视频在线观看| 久久黄色一级片| 免费无码AV片在线观看中文| 国产迷奸在线看| 亚洲欧美一级一级a| 91探花国产综合在线精品| 免费看一级毛片波多结衣| 日韩欧美国产中文| AV色爱天堂网| 二级特黄绝大片免费视频大片| 在线看片中文字幕| 久久这里只有精品免费| a网站在线观看| 欧洲高清无码在线| 真实国产乱子伦视频| 色妺妺在线视频喷水| 九九九精品视频| 欧美日韩成人| 国产AV无码专区亚洲精品网站| 91福利片| 亚洲 日韩 激情 无码 中出| 热思思久久免费视频| 一级片一区| 视频国产精品丝袜第一页| 亚洲无卡视频| 成人亚洲国产| 日本国产精品一区久久久| 深夜福利视频一区二区| 亚洲日本韩在线观看| 亚洲不卡影院| 亚洲成年人片| 久久精品国产国语对白| 免费可以看的无遮挡av无码| 伊人色综合久久天天| 国产色网站| 国产麻豆91网在线看| 性网站在线观看|