繁体   English   中英

在 Cuda 中使用最大共享内存

[英]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 的共享内存需要两件事:

  1. 上面已经描述的选择加入机制
  2. 内核代码中的动态而非静态共享内存分配

动态示例:

extern __shared__ int shared_mem[];

静态示例:

__shared__ int shared_mem[1024];

动态分配的共享内存还需要在内核启动配置参数中传递一个大小(问题中给出了一个示例)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM