如何在CUDA中使用动态分配的外部共享内存的示例:Use dynamic shared memory allocation for two different vectors
extern __shared__ float array[];
__device__ void func() // __device__ or __global__ function
{
short* array0 = (short*)array;
float* array1 = (float*)&array0[128];
int* array2 = (int*)&array1[64];
}
但是,当我必须手动将其分配给变量时,为什么还要使用extern动态分配的共享内存呢?
我认为以下解决方案没有任何缺点:
__device__ void func() // __device__ or __global__ function
{
__shared__ float array[MAXIMALLY_NEEDED_SIZE];
short* array0 = (short*)array;
float* array1 = (float*)&array0[128];
int* array2 = (int*)&array1[64];
}
显然,使用第一个解决方案,我可以节省一些共享内存。但这对我有什么帮助呢?
(我觉得那里有动态分配内存的充分理由,但是我没有看到它,所以我可能缺乏理解。这就是我问的原因。)
答案 0 :(得分:3)
使用动态分配的共享内存(而不是静态分配)的原因类似于您可能想要动态地而不是静态地分配任何的一个原因:在编译时,您不要知道你想要的分配大小。
你给出的例子并没有很好地说明这一点。该示例的最初目的是说明如何在动态分配的情况下处理驻留在共享内存中的多个独立对象,而不是突出显示动态与静态共享内存的使用。
显然,使用第一个解决方案,我可以节省一些共享内存。但这对我有什么帮助呢?
保存共享内存可能有价值的一个可能原因是,它可能影响占用,从而影响性能。
假设我有一个并行缩减代码,并假设它使用共享内存作为主要缩减介质。通常,我需要的共享内存量将与我在threadblock中使用的线程数相关。现在让我们假设根据我遇到的确切问题,我可能想调整每个线程块的线程数,在运行时。
如果我启动256个线程的线程块,并且我在64位整数上进行并行减少,那么每个线程块可能需要256 * 8bytes(2KB)的共享内存。如果我启动1024个线程的线程块,每个线程块需要8KB的共享内存(这是最大的可能)。
如果我只是对这个值进行硬编码,以便它可以在编译时用作静态分配的一部分,那么我需要使用8KB的值。这将限制我在大多数GPU上最多占用6个线程块(6 * 8KB = 48KB最大共享内存),即使我正在启动只有256个线程的线程块。 (如果我需要任何共享内存用于任何其他目的,那么我的最大占用率将少于6个线程块。)
使用动态分配,1024个线程的线程块仍具有与上述相同的限制,但是使用256个线程启动的线程块将能够在理论上实现更高的占用率(至少基于共享内存限制),这可以转化为更高的性能。
答案 1 :(得分:0)
使用共享内存的另一个有效原因是内存合并,否则可能是串行操作。请参阅http://devblogs.nvidia.com/parallelforall/using-shared-memory-cuda-cc/