mch*_*hen 34 memory cuda global shared-memory
我对如何在CUDA中使用共享和全局内存感到困惑,尤其是对于以下内容:
cudaMalloc()
,我们得到一个指向共享或全局内存的指针吗?将变量存储在共享内存中与通过内核传递其地址相同吗?也就是说,而不是
__global__ void kernel() {
__shared__ int i;
foo(i);
}
Run Code Online (Sandbox Code Playgroud)
为什么不等同呢
__global__ void kernel(int *i_ptr) {
foo(*i_ptr);
}
int main() {
int *i_ptr;
cudaMalloc(&i_ptr, sizeof(int));
kernel<<<blocks,threads>>>(i_ptr);
}
Run Code Online (Sandbox Code Playgroud)关于全局与共享内存中的特定速度问题存在很多问题,但没有一个问题包含何时在实践中使用任何一个内容的概述.
非常感谢
1--*_*--1 47
当我们使用cudaMalloc()时
为了将数据存储在可以传回主机的gpu上,我们需要有一个存储的内存,直到它被释放,将全局内存看作具有生命的堆空间直到应用程序关闭或被释放,它是可见的到具有指向该内存区域的指针的任何线程和块.共享内存可以被视为具有生命的堆栈空间,直到内核块完成,可见性仅限于同一块内的线程.所以cudaMalloc用于在全局内存中分配空间.
我们得到一个指向共享或全局内存的指针吗?
您将获得一个指向驻留在全局内存中的内存地址的指针.
全局内存是否驻留在主机或设备上?
全局内存驻留在设备上.但是,有一些方法可以使用映射内存将主机内存用作"全局"内存,请参阅:CUDA归零内存注意事项,但由于总线传输速度限制,可能速度较慢.
是否有任何尺寸限制?
全局内存的大小取决于卡到卡,从无到8GB.共享内存取决于计算能力.低于计算能力2.x的任何东西每个多处理器最多有16KB的共享内存(多处理器的数量因卡而异).计算能力为2.x或更高的卡每个多处理器最多可以有48KB的共享内存.
如果使用映射内存,唯一的限制是主机在内存中的容量.
哪个访问速度更快?
就原始数字而言,共享内存要快得多(共享内存~1.7TB/s,而全局内存~150GB/s).但是,为了做任何你需要用某些东西填充共享内存的东西,你通常会从全局内存中取出.如果内存访问全局内存是合并的(非随机),您将获得高达150-200GB/s的速度,具体取决于卡及其内存接口.
共享内存的使用是指您需要在一个线程块内重用已经从全局内存中提取或评估的数据.因此,不要再次从全局内存中提取,而是将其放在同一块中的其他线程的共享内存中以查看和重用.
将变量存储在共享内存中与通过内核传递其地址相同吗?
不,如果您传递任何地址,它始终是全局内存的地址.在主机中,您无法设置共享内存,除非您将其作为常量传递,内核将共享内存设置为该常量,或者将地址传递给全局内存,并在需要时由内核提取.
sga*_*zvi 10
全局内存的内容对于网格的所有线程都是可见的.任何线程都可以读写全局内存的任何位置.
共享内存对于网格的每个块是独立的.块的任何线程都可以读取和写入该块的共享内存.一个块中的线程无法访问另一个块的共享内存.
cudaMalloc
总是分配全局内存.16 KB/Block
,计算2.0到7.0具有48 KB/Block
共享内存.更新:
计算能力设备7.0(Volta Architecture)允许在每个块上分配高达96 KB的共享内存,前提是满足以下条件.
cudaFuncSetAttribute
.__global__ void MyKernel(...)
{
extern __shared__ float shMem[];
}
int bytes = 98304; //96 KB
cudaFuncSetAttribute(MyKernel, cudaFuncAttributeMaxDynamicSharedMemorySize, bytes);
MyKernel<<<gridSize, blockSize, bytes>>>(...);
Run Code Online (Sandbox Code Playgroud)