我在理解CUDA中的共享记忆组织和3个愚蠢的问题时遇到了一些麻烦。
1)Cuda c programming guide说“每个多处理器都有一个L1缓存,所有多处理器共享一个L2缓存,这两个缓存都用于缓存对本地或全局内存的访问,包括临时寄存器溢出”。他们将L2缓存称为“共享内存”。
我错误地说所有SM共享的L2缓存和用于存储__shared__
限定符变量的共享内存是不同的东西?
2)我有GeForce 630M和Compute Capability 2.1,所以结果如下:
cudaDeviceProp info;
cudaGetDeviceProperties(&info,0);
printf("%d kB\n",info.sharedMemPerBlock/1024);
是48 kB。
这是否意味着它是一个块的共享内存的总大小和共享内存的最大可能大小?我的意思是,例如,我即将使用N个块启动内核,所以每个块只能使用48 / N kB?
3)
之间有什么区别吗?extern __shared__ float shared[];
和
__shared__ float shared[];
答案 0 :(得分:0)
你是对的。二级缓存和共享内存是两回事。 L2是"共享"在所有SM中。他们不称之为“共享记忆”#34;我能看到。它是一个单一的设备范围的资源。 fermi whitepaper将提供各种资源之间关系的其他说明。 L2是设备范围的。 L1 / Shared是每个SM资源。
48KB是单个线程块可用的最大值,它也是设备上可用的最大值(每SM)。它是当前驻留在SM上的所有线程块在物理上(不是逻辑上)共享的。如果单个线程块使用14KB的共享内存,那么(仅考虑共享内存)在SM上的任何给定时间可以驻留多达3个线程块。那3个线程块将共享物理资源(总共48KB,每个线程块14KB),但是它们每个都有自己的逻辑部分(即,线程块无法看到属于另一个线程块的共享内存。)如果单个线程块使用了40KB的共享内存,在任何给定时间只有其中一个可以驻留在SM上。
区别在于第一种情况是动态分配的,并且需要在内核启动时传递共享内存大小(分配),第二种情况是静态分配,并要求您指定大小:
__shared__ float shared[32];
^^
something is required here for a static allocation
您可能需要参考this最近的问题/答案,以获得有关静态和动态__shared__
分配之间差异的更多讨论,以及动态案例所需的内核参数。