[英]Using maximum shared memory in Cuda
我无法使用超过 48K 的共享内存(在 V100、Cuda 10.2 上)
我打电话
cudaFuncSetAttribute(my_kernel,
cudaFuncAttributePreferredSharedMemoryCarveout,
cudaSharedmemCarveoutMaxShared);
在第一次启动my_kernel
之前。
我在my_kernel
使用启动边界和动态共享内存:
__global__
void __launch_bounds__(768, 1)
my_kernel(...)
{
extern __shared__ float2 sh[];
...
}
内核是这样调用的:
dim3 blk(32, 24); // 768 threads as in launch_bounds.
my_kernel<<<grd, blk, 64 * 1024, my_stream>>>( ... );
内核调用后的cudaGetLastError()
返回cudaErrorInvalidValue
。
如果我使用 <= 48 K 的共享内存(例如, my_kernel<<<grd, blk, 48 * 1024, my_stream>>>
),它就可以工作。
编译标志是:
nvcc -std=c++14 -gencode arch=compute_70,code=sm_70 -Xptxas -v,-dlcm=cg
我错过了什么?
从这里:
计算能力 7.x 设备允许单个线程块寻址共享内存的全部容量:Volta 上为 96 KB,图灵上为 64 KB。 依赖每块超过 48 KB 共享内存分配的内核是特定于体系结构的,因此它们必须使用动态共享内存(而不是静态大小的数组),并且需要使用 cudaFuncSetAttribute() 进行显式选择,如下所示:
cudaFuncSetAttribute(my_kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, 98304);
当我将该行添加到您显示的代码中时,无效值错误就会消失。 对于图灵设备,您可能希望将该数字从 98304 更改为 65536。当然,对于您的示例,65536 也足够了,尽管如问题标题所述,还不足以使用 volta 上可用的最大值。
以类似的方式,Ampere 设备上的内核应该能够使用最多 160KB 的共享内存 (cc 8.0) 或 100KB (cc 8.6),动态分配,使用上述选择加入机制,编号 98304 更改为 163840(对于cc 8.0,例如)或 102400(对于 cc 8.6)。
请注意,以上涵盖了 Volta (7.0) Turing (7.5) 和 Ampere (8.x) 情况。 具有 7.x 之前计算能力的 GPU 无法处理每个线程块超过 48KB 的空间。 在某些情况下,这些 GPU 的每个多处理器可能有更多的共享内存,但这样做是为了在某些线程块配置中允许更大的占用。 程序员不能使用超过 48KB 的每个线程块。
虽然它不属于这里提供的代码(它已经在使用动态共享内存分配),但请注意摘录文档引用,在支持它的设备上使用超过 48KB 的共享内存需要两件事:
动态示例:
extern __shared__ int shared_mem[];
静态示例:
__shared__ int shared_mem[1024];
动态分配的共享内存还需要在内核启动配置参数中传递一个大小(问题中给出了一个示例)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.