CUDA——內(nèi)存層級(jí)

Memory Hierarchy
GPU Hardware
Memory Abstraction

全局內(nèi)存 global memory

  • 獨(dú)立于GPU核心的硬件RAM
  • GPU絕大多數(shù)內(nèi)存空間都是全局內(nèi)存
  • 全局內(nèi)存的IO是GPU上最慢的IO形式(除了訪問(wèn)host端內(nèi)存)

通過(guò)cache L2(CC>=3.0)訪問(wèn),cache line 大小128 bytes ,每個(gè)線程操作盡量少的cache line,速度更快

Examples of Global Memory Accesses. Examples of Global Memory Accesses by a Warp, 4-Byte Word per Thread, and Associated Memory Transactions for Compute Capabilities 2.x and Beyond

共享內(nèi)存 shared memory

  • SM(SM = streaming multiprocessor)中的內(nèi)存空間
  • 最大48KB
  • 作用域是線程塊
靜態(tài)分配語(yǔ)法
__shared__ float data[1024];
Declared in the kernel function, nothing in host code

動(dòng)態(tài)分配語(yǔ)法
Host:
kernel<<<grid_dim, block_dim, numBytesShMem>>>(args);
Device (in kernel):
extern __shared__ float s[];

多個(gè)動(dòng)態(tài)分配的變量  需要額外注意對(duì)齊
extern __shared__ int s[];
int *integerData = s;                        // nI ints
float *floatData = (float*)&integerData[nI]; // nF floats
char *charData = (char*)&floatData[nF];      // nC chars

myKernel<<<gridSize, blockSize, nI*sizeof(int)+nF*sizeof(float)+nC*sizeof(char)>>>(...);

共享內(nèi)存塊沖突

共享內(nèi)存分成相同大小的內(nèi)存塊,實(shí)現(xiàn)高速并行訪問(wèn),但是當(dāng)多個(gè)線程的請(qǐng)求地址映射到同一個(gè)內(nèi)存塊block時(shí),訪問(wèn)是串行的

步幅stride為n時(shí) 最大公約數(shù)為1,即gcd(n,32)==1 ,訪問(wèn)共享內(nèi)存可以避免塊沖突

Strided Shared Memory Accesses. Examples for devices of compute capability 3.x (in 32-bit mode) or compute capability 5.x and 6.x
Left
Linear addressing with a stride of one 32-bit word (no bank conflict).
Middle
Linear addressing with a stride of two 32-bit words (two-way bank conflict).
Right
Linear addressing with a stride of three 32-bit words (no bank conflict).
Irregular Shared Memory Accesses. Examples for devices of compute capability 3.x, 5.x, or 6.x
Left
Conflict-free access via random permutation.
Middle
Conflict-free access since threads 3, 4, 6, 7, and 9 access the same word within bank 5.
Right
Conflict-free broadcast access (threads access the same word within a bank).

本地內(nèi)存 local memory

位于堆棧中,不在寄存器中的所有內(nèi)容
作用域?yàn)樘囟ň€程
存儲(chǔ)在global內(nèi)存空間中,速度比寄存器慢很多

寄存器溢出 register spilling

內(nèi)核使用的寄存器比可用的寄存器多,存儲(chǔ)到local memory中

L1 cache

  • 每個(gè)SM都有自己的L1 cache
  • 可配置大小16KB/48KB cudaFuncSetCacheConfig
  • 2.x Fermi - caches local & global memory
  • 3.x 及以上 Kepler, Maxwell - only caches local memory

L2 cache

  • 緩存 local and global memory
  • 被所有的SM共享
  • 大約為1MB

常量?jī)?nèi)存 constant memory

  • 屬于全局內(nèi)存,大小64KB
  • 線程請(qǐng)求同一個(gè)數(shù)據(jù)時(shí)很快,請(qǐng)求不同的數(shù)據(jù)時(shí)性能下降
  • 在運(yùn)行中不變,所有constant變量的值必須在kernel啟動(dòng)之前從host設(shè)置
  • __global__ 函數(shù)參數(shù)通過(guò) constant memory穿的到device端, 限定4 KB,即kernel參數(shù)通過(guò)常量?jī)?nèi)存?zhèn)鬟f
__constant__ float constData[256]; 
float data[256]; 
cudaMemcpyToSymbol(constData, data, sizeof(data)); 
cudaMemcpyFromSymbol(data, constData, sizeof(data));

常量緩存 constant cache

  • 每個(gè)SM上大小8KB,CC>=5.0大小為10KB
  • 把一個(gè)內(nèi)存地址廣播到所有的warp線程
  • 可以加載靜態(tài)索引數(shù)據(jù),通過(guò) “l(fā)oad uniform” (LDU)指令

紋理內(nèi)存空間 texture memory

類似constant memory,是只讀內(nèi)存,以某種形式訪問(wèn)的時(shí)候可以提升性能。原本是用在OpenGL和DirectX渲染管線中的。
有用的特點(diǎn):

  • 不需考慮要聚合coalescing訪問(wèn)的問(wèn)題
  • 通過(guò)“CUDA Array”進(jìn)行緩存的2D或3D空間的數(shù)據(jù)位置
  • 在1D,2D或3D數(shù)組上進(jìn)行快速插值
  • 將整數(shù)轉(zhuǎn)換為“unitized”浮點(diǎn)數(shù)

用例:

  1. 通過(guò)紋理緩存和CUDA數(shù)組讀取輸入數(shù)據(jù),以利用空間緩存
  2. 利用數(shù)字紋理功能。
  3. 與OpenGL和通用計(jì)算機(jī)圖形的交互

紋理緩存 read-only texture cache

CC ≥ 3.5 大多數(shù)的 __restrict__ 變量自動(dòng)加載到紋理緩存中了
通過(guò) __ldg函數(shù)強(qiáng)行加載到緩存

// 2D float texture 
texture<float, cudaTextureType2D, cudaReadModeElementType> texRef;

cudaArray* cuArray; 
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>; 
cudaMallocArray(&cuArray, &channelDesc, width, height);
cudaMemcpyToArray(cuArray, 0, 0, h_data, size,
                      cudaMemcpyHostToDevice);

// Set texture reference parameters 
texRef.addressMode[0] = cudaAddressModeWrap; 
texRef.addressMode[1] = cudaAddressModeWrap; 
texRef.filterMode = cudaFilterModeLinear; 
texRef.normalized = true; 

// Bind the array to the texture reference 
cudaBindTextureToArray(texRef, cuArray, channelDesc);
cudaUnbindTexture (const textureReference *texref);
cudaFreeArray(cuArray);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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