天天看點

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上一篇介紹了CUDA記憶體空間。GPU對片外DRAM的通路往往是訪存性能的瓶頸。[1]第四章的後半部分,通過Global記憶體為例,說明了GPU通路DRAM的工作模式以及在該模式下,如何高效的使用DRAM記憶體。同樣的内容也可以參考[2]的5.3.2一節。

參考文獻:

[1] PROFESSIONAL CUDA C Programming. John Cheng, Max Grossman, Ty McKercher.

[2] CUDA C PROGRAMMING GUIDE

記憶體通路模式

GPU對片外DRAM的通路延遲大,帶寬低,導緻其成為很多應用的性能瓶頸。是以對DRAM通路的進一步優化可以有效改善程式性能。優化之前,首先看一下GPU對記憶體的通路模式。

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

如上圖所示,DRAM記憶體的讀寫在實體上是從片外DRAM->片上Cache->寄存器。 其中,片外DRAM到片上Cache是主要性能瓶頸。DRAM到Cache之間的一次傳輸(transaction)設計為32,64或者128位元組,并且記憶體位址按照32,64或者128位元組的間隔對齊。

後文中transaction特指裝置記憶體(DRAM)到片記憶體儲(Cache)的傳輸。

以讀資料為例,DRAM資料首先進入L2 Cache,之後根據GPU架構的不同,有些會繼續傳輸到L1 Cache,最後進入線程寄存器。L2 cache是所有SM共有,而L1 cache是SM私有。如果使用了L1+L2 Cache,那麼執行一次DRAM到Cache之間的傳輸(transaction),是128位元組。如果僅使用L2 Cache,那麼就是32位元組。是否啟用L1 Cache取決于GPU架構與編譯選項 。

關閉L1 cache
-Xptxas -dlcm=cg

打開L1 cache
-Xptxas -dlcm=ca
           

由于采用SIMT的架構,GPU對記憶體的通路指令是由warp發起的,即warp中每個線程同時執行記憶體操作指令,不過每個線程所通路的資料位址可以不同,GPU會根據這些不同的位址發起一次或多次DRAM->Cache的傳輸(transaction),直到所有線程都拿到各自所需的資料(Cache->Registers)。顯然,我們可以通過減少DRAM->Cache的transaction次數來優化程式性能。

回憶門:Stalled warp。執行模型一文中提到,warp執行記憶體指令時會有很長的延遲,此時warp進入Stalled狀态,warp排程器排程其他eligible warp執行。

記憶體指令延遲的原因:

  • 通路裝置記憶體本身存在大的延遲。
  • SIMT的執行模型,意味着隻有當warp内所有32個線程都得到了資料後,才會從Stalled态轉為Eligible态。

最好的情況下,GPU發起一次DRAM->Cache的transaction就把Warp中所有線程所需的資料全部擷取到Cache,最壞的情況下,則需要32次transaction。

對齊與合并通路

通過上面的簡單分析不難想到,優化全局記憶體的通路性能,需要考慮下面兩個方面,

  • 記憶體對齊通路(Aligned memory access): DRAM->Cache transaction,首位址是32或128位元組的倍數。
  • 記憶體合并通路(Coalesced memory access): Warp内線程通路連續記憶體塊。

下圖為一個理想的對齊合并記憶體通路的例子,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

Warp内每個線程需要4個位元組的資料,且總共32*4=128個位元組是連續的,起始位址為128。此時隻需一次128位元組的memory transactioin(DRAM->Cache)。

下圖為非對齊,非合并的情況,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

這種情況下需要3個128位元組的memory transaction,一個從記憶體位址0->127,為标記為1的線程取值,, 一個從128->255,為标記2的線程取值,一個從256->383,為标記3的線程取值。

下面以Global Memory為例,展開讨論不同情況下記憶體通路的性能。

Global Memory Read

根據是否使用L1 cache,可分為兩種情況讨論,

  • Cached load(使用L1 cache)
  • Uncached load(不适用L1 cache)

Cached Load

使用L1 cache,memory transaction的以L1 cache line的大小128位元組為間隔訪存。

合并對齊通路(Aligned, coalesced):

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上圖,warp内線程通路的位址在128~256之間,每個線程需要4個位元組,所有線程所需記憶體位址按照線程ID連續排列。隻需執行一個128位元組的transaction即可滿足所有線程的需求。此時總線使用率為100%,即在這次transaction中,記憶體帶寬得以充分使用,沒有多餘的資料。

另一種情況,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

此時,warp的線程通路的資料在128~256之間,每個線程需要4個位元組,但是記憶體位址沒有按照線程ID排序。與之前的例子相同,一次128位元組的transaction即可滿足要求,且總線使用率為100%。

連續,不對齊,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上圖warp需要連續的128位元組,但是記憶體的首位址沒有128位元組對齊。此時需要兩次128位元組的transaction,總線使用率為50%(總共讀了256個位元組,實際使用128位元組)

如果warp内的線程通路同一4位元組資料,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上圖warp内所有線程通路了相同4個位元組,需要一次128位元組的transaction,總線使用率4/128=3.125%。

最壞情況下,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

Warp所需的資料散落在global memory裡,那麼需要最多32次128位元組的transaction。

再來看不使用L1 cache的情況。

Uncached Load

如果不使用L1 cache,一次記憶體傳輸由1, 2或4個segments完成,每個segment為32位元組, 并且按照32位元組對齊。顯然這種情況下資料傳輸得到了更精細的劃分(最小32位元組),這會帶來更高效的非對齊,非合并的記憶體通路。

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上圖是一個理想的情況下,對齊合并的記憶體通路,隻需一個4 segment的transaction,總線使用率100%。

非對齊情況,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上圖warp需要連續的128位元組資料,但是首位址并未和32位元組對齊,此時128位元組的資料最多分布在5個segment内,是以總線使用率至少為80%。顯然要比使用L1 cached的時候更好。

再來看warp通路同一個4位元組資料的情況,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

此時的總線使用率為4/32 = 12.5%,也要比使用L1 cache時(3.125%)要好。

考慮最壞的情況,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

32個線程所需的資料散落在至多32個segment裡。散落在32個32位元組的segment裡顯然要比散落在32個128位元組的情況要好。

Read-Only cache: Read-Only cache原本用于紋理記憶體的緩存。GPU 3.5以上的版本可以使用該緩存替代L1,作為Global記憶體的緩存。此cache采用32位元組對齊間隔,是以比原128位元組的緩沖區更适合非對齊非合并的情況。

Global Memory Write

記憶體寫操作情況要簡單的多,Fermi/Kelper的L1 cache并不支援寫操作。記憶體寫僅通過L2 cache寫入裝置記憶體。與Uncached Load類似,transaction分為1, 2, 4個segment,每個segment32位元組。

理性情況下,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

warp寫入連續的128個位元組,僅需一個4-segments的transaction。

對齊,但是不合并,

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

對齊,但散落在192個位元組的空間内,則需要3個1-segment的transaction。

計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

64位元組的連續存儲,需要一個2-segment的transaction。

AoS與SoA

[1]中讨論了兩種資料組織形式,Array of structures 和 Structure of array.

//Array of structures (AoS)
struct innerStruct {
    float x;
    float y;
};

struct innerStruct myAoS[N];

//Structure of array
struct innerArray {
    float x[N];
    float y[N];
};

struct innerArray moa;
           
計算機視覺大型攻略 —— CUDA(3)記憶體模型(二)Aligned and Coalesced記憶體通路記憶體通路模式對齊與合并通路

上圖為AoS, SoA的記憶體結構。采用AoS的形式,Warp線程通路x的時候,會把y的值也載入cache。浪費了50%的帶寬。而SoA就不存在這個問題。是以推薦采用SoA的形式組織資料。

訪存性能瓶頸通常發生在片外DRAM的讀寫上,除了減少裝置記憶體的transaction以及提高總線使用率之外,在程式設計時還應盡量減少對Global記憶體的通路次數,這部分在下一篇的共享記憶體裡有所涉及。

繼續閱讀