cuda全局內(nèi)存中的“分區(qū)沖突”

CUDA將GPU的內(nèi)存模型暴露給開發(fā)人員,包括全局內(nèi)存、常量/紋理內(nèi)存、共享內(nèi)存、本地內(nèi)存、寄存器,不同類型內(nèi)存的讀取和訪問的模式有所差別。在不合理的訪問模式下,全局內(nèi)存訪問可能發(fā)生“分區(qū)沖突”(partion camping),其類似于共享內(nèi)存中的bank conflict,只不過粒度較大(資料[1]中介紹的架構(gòu)下分區(qū)寬度為256字節(jié),而bank寬度通常為4或8字節(jié))。全局內(nèi)存按照256字節(jié)劃分為多個分區(qū),所有針對全局內(nèi)存的訪問操作由不同的分區(qū)完成,如果多個內(nèi)存訪問操作地址落在同一個分區(qū)中,這些訪問操作將被串行處理,對性能有較大的影響(全局內(nèi)存訪問本身就是高延遲的操作)。下圖是一個分區(qū)總數(shù)為8的全局內(nèi)存的分區(qū)情況。


以全局內(nèi)存分區(qū)數(shù)量為8為例,下面圖片給出了發(fā)生和不發(fā)生”分區(qū)沖突“的全局內(nèi)存訪問情況。


在發(fā)生”分區(qū)沖突“時,SM-1到SM-30的全局內(nèi)存訪問操作完全變成串行訪問(全部由分區(qū)1處理)。我們下面分別給出發(fā)生和不發(fā)生”分區(qū)沖突“的核函數(shù)示例,通過執(zhí)行該核函數(shù)可以對”分區(qū)沖突”對性能的影響有大致了解。

不發(fā)生“分區(qū)沖突”

//TYPEcanbea2-,4-oran8-byteword
__global__ void readBenchmark(TYPE *d_arr){
    //assignuniquepartitionstoblocks,
    int numOfPartitions=8;
    int curPartition=blockIdx.x%numOfPartitions;
    int partitionSize=256;//256bytes
    int elemsInPartition=partitionSize/sizeof(int);
    //jumptouniquepartition
    int startIndex=elemsInPartition*curPartition;
    TYPE readVal=0;
    //Loopcounter’x’ensurescoalescing
    for(int x=0;x<ITERATIONS;x+=16){
    /*offsetguaranteestorestrictthe
    indextothesamepartition*/
        int offset=((threadIdx.x+x)%elemsInPartition);
        int index=startIndex+offset;
        //Readfromglobalmemorylocation
        readVal=d_arr[index];
    }
    /*Writeoncetomemorytopreventtheabove
    codefrombeingoptimizedout*/
    d_arr[0]=readVal;
}

發(fā)生“分區(qū)沖突”

//TYPEcanbea2-,4-oran8-byteword
__global__ void readBenchmarkPC(TYPE *d_arr){
    int partitionSize=256;//256bytes
    int elemsInPartition=partitionSize/sizeof(TYPE);
    TYPE readVal=0;
    //Loopcounter’x’ensurescoalescing.
    for(int x=0;x<ITERATIONS;x+=16){
        /*allblocksreadfromasinglepartition
        tosimulatePartitionCamping*/
        int index=((threadIdx.x+x)%elemsInPartition);
        //Readfromglobalmemorylocation
        readVal=d_arr[index];
    }
    /*Writeoncetomemorytopreventtheabove
    codefrombeingoptimizedout*/
    d_arr[0]=readVal;
}

具體執(zhí)行配置:網(wǎng)格配置為256x1,線程塊配置為32x32,數(shù)據(jù)類型(TYPE)為整型,數(shù)據(jù)個數(shù)為256x8,迭代次數(shù)為4096x4096,設(shè)備為RTX2080ti。下面是執(zhí)行結(jié)果。


從圖中我們可以看到,即使在第一個核函數(shù)執(zhí)行更多指令的情況下,“分區(qū)沖突”還是使核函數(shù)的性能下降了4倍左右。

注意:

在編譯時需要禁用一級緩存 ,否則讀操作可能由緩存完成而不訪問全局內(nèi)存,從而無法觀察到“分區(qū)沖突”現(xiàn)象。

參考資料

  1. 書籍《cuda C權(quán)威編程指南》
  2. 論文《Bounding the Effect of Partition Camping in GPU Kernels》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容