在内核函数中创建对象时CUDA内存访问冲突

时间:2015-02-12 15:05:06

标签: c++ memory cuda access-violation heap-memory

使用operator new在CUDA内核函数中分配大内存我在每次启动时将cudaLimitMallocHeapSize的值设置为可用设备内存的大小~1.7-1.8G。但是如果我尝试在内核函数中创建一个对象,我会在内存检查器抛出的行i = 42;中获得内存访问冲突。 这是代码:

class Test
{
private:
    int i;

public:
    __device__ Test()
    {
        i = 42;
    }
};

__global__ void test()
{
    Test *m = new Test();
    if (m == NULL)
    {
        printf("m == NULL\n");
    }
    else
    {
        printf("OK\n");
    }
}

int main(int argc, char *argv[])
{
    size_t free;
    size_t total;
    cudaMemGetInfo(&free, &total);
    cudaCheckError(cudaDeviceSetLimit(cudaLimitMallocHeapSize, free));

    test << <1, 1 >> >();
    cudaCheckError(cudaDeviceSynchronize());
    cudaCheckError(cudaDeviceReset());
    return 0;
}

但是在此异常对象Test *m之后是一个普通对象,其地址在设备内存中,其字段i等于42。 如果我删除此类的构造函数,则在函数中的cuda源文件device_functions.h中引发相同的异常

static __forceinline__ void* memset(void *dest, int c, size_t n)
{
  __nvvm_memset((unsigned char *)dest, (unsigned char)c, n, /*alignment=*/1);
  return dest;
}

如果我将堆大小设置为1 * 1024 * 1024 * 1024 = 1G - 会发生相同的异常。

750 MB - 毫无例外。

900 MB - 毫无例外。

1000 MB - 没有例外。

1020 MB - 例外。

为什么会这样? 堆大小是否低于可用内存的大小?

我使用Visual Studio Ultimate 2013和Nsight 4.1。 该设备是GeForce GTX 650 Ti,具有2.0的计算能力。

提前致谢。


UPD1:设备上共有2GB DDR5内存。操作系统是Windows 8.1 Professional x64。

UPD2:我可以使用cudaMalloc()从主机代码中分配大于1GB的内容。

2 个答案:

答案 0 :(得分:1)

我检查了你的卡的规格,它显示只有1024MB的GDDR5设备内存。

这意味着如果你想在卡上有一堆1020MB的设备内存,你将只剩下4MB供驱动程序使用。我想这不会很好。

如果尝试使用内存较多的GPU,则应该能够设置更高的堆大小。


编辑v1 :如果你有一张RAM含量较高的卡,你可以尝试从主机代码动态分配,缓冲区大于1024 MB?如果你不能这样做,那可能是司机的限制。

答案 1 :(得分:0)

通过安装CUDA 7.0版本解决了问题。