Memory 在cuda中使用静态分配内存时的全局设备内存大小限制

Memory 在cuda中使用静态分配内存时的全局设备内存大小限制,memory,cuda,Memory,Cuda,我认为全局内存的最大大小应该只受GPU设备的限制,无论它是使用\uuuuu设备\uuuuuuu管理的\uuuuuuuu>静态分配还是使用cudamaloc动态分配 但是我发现,如果使用\uuu设备\uuuuu管理的\uuuuu方式,我可以声明的最大数组大小远小于GPU设备限制 最简单的工作示例如下所示: #include <stdio.h> #include <cuda_runtime.h> #define gpuErrchk(ans) { gpuAssert((ans

我认为全局内存的最大大小应该只受GPU设备的限制,无论它是使用
\uuuuu设备\uuuuuuu管理的\uuuuuuuu>静态分配还是使用
cudamaloc
动态分配

但是我发现,如果使用
\uuu设备\uuuuu管理的\uuuuu
方式,我可以声明的最大数组大小远小于GPU设备限制

最简单的工作示例如下所示:

#include <stdio.h>
#include <cuda_runtime.h>

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true)
{
   if (code != cudaSuccess)
   {
      fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
      if (abort) exit(code);
   }
}

#define MX 64
#define MY 64
#define MZ 64

#define NX 64
#define NY 64

#define M (MX * MY * MZ)


__device__ __managed__ float A[NY][NX][M];
__device__ __managed__ float B[NY][NX][M];

__global__ void swapAB()
{
    int tid = blockIdx.x * blockDim.x + threadIdx.x;
    for(int j = 0; j < NY; j++)
        for(int i = 0; i < NX; i++)
            A[j][i][tid] = B[j][i][tid];
}


int main()
{
    swapAB<<<M/256,256>>>();
    gpuErrchk( cudaPeekAtLastError() );
    gpuErrchk( cudaDeviceSynchronize() );
    return 0;
}
输出警告:

warning: overflow in implicit constant conversion.
当我运行生成的可执行文件时,错误显示:

GPUassert: an illegal memory access was encountered test.cu
令人惊讶的是,如果我通过
cudamaloc
API使用相同大小(8GB)的动态分配全局内存,则不会出现编译警告和运行时错误

我想知道CUDA中静态全局设备内存的可分配大小是否有特殊限制

谢谢


PS:OS和CUDA:CentOS 6.5 x64,CUDA-7.5。

这似乎是CUDA运行时API的一个限制。根本原因是此功能(在CUDA 7.5中):

它只接受任何静态声明的设备变量大小的带符号int。这会将最大大小限制为2^31(2147483648)字节。您看到的警告是因为CUDA前端正在发出样板代码,其中包含对
\uu cudaResgisterVar
的调用,如下所示:

__cudaRegisterManagedVariable(__T26, __shadow_var(A,::A), 0, 4294967296, 0, 0);
__cudaRegisterManagedVariable(__T26, __shadow_var(B,::B), 0, 4294967296, 0, 0);

问题的根源是4294967296。该大小将使带符号整数溢出,并导致API调用中断。因此,目前每个静态变量的容量限制为2Gb。如果这对您的应用程序来说是一个严重的问题,我建议您将其作为NVIDIA的错误提出。

没错,静态内存限制为2Gb。我会试着把它当作虫子来提。顺便说一句,我之所以要使用静态声明的多维数组,是因为我发现它们对于我的多维物理建模代码更有效。在3D模具中寻址数据元素时,使用1D动态分配数组会演化出许多整数操作。我已经尝试过CUDA 8.0 RC,但该错误仍然存在:(
__cudaRegisterVar(
        void **fatCubinHandle,
        char  *hostVar,
        char  *deviceAddress,
  const char  *deviceName,
        int    ext,
        int    size,
        int    constant,
        int    global
);
__cudaRegisterManagedVariable(__T26, __shadow_var(A,::A), 0, 4294967296, 0, 0);
__cudaRegisterManagedVariable(__T26, __shadow_var(B,::B), 0, 4294967296, 0, 0);