在内核函数中创建对象时发生 CUDA 内存访问冲突
CUDA memory access violation when creating an object in kernel function
为了使用运算符 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。
如果我删除此 class 的构造函数,则在函数
中的 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。
该设备是具有计算能力 2.0 的 GeForce GTX 650 Ti。
提前致谢。
UPD1: 设备总内存为 2GB DDR5。 OS 是 Windows 8.1 Professional x64。
UPD2: 我可以使用 cudaMalloc()
.
从主机代码分配大于 1GB 的空间
我检查了您的卡的规格,它显示只有 1024MB 的 GDDR5 设备内存。
这意味着如果你想在卡上拥有 1020MB 的设备内存堆,你将只剩下 4MB 供驱动程序使用。我想这不是很好。
如果您尝试使用具有更高内存量的 GPU,您应该能够设置更大的堆大小。
编辑 v1:如果您的卡具有更高的 RAM,您可以尝试从主机代码动态分配 ,超过 1024 MB 的缓冲区?如果你不能这样做,那可能是驱动程序的限制。
问题已通过安装 CUDA 7.0 版本解决。
为了使用运算符 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。
如果我删除此 class 的构造函数,则在函数
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。 该设备是具有计算能力 2.0 的 GeForce GTX 650 Ti。
提前致谢。
UPD1: 设备总内存为 2GB DDR5。 OS 是 Windows 8.1 Professional x64。
UPD2: 我可以使用 cudaMalloc()
.
我检查了您的卡的规格,它显示只有 1024MB 的 GDDR5 设备内存。
这意味着如果你想在卡上拥有 1020MB 的设备内存堆,你将只剩下 4MB 供驱动程序使用。我想这不是很好。
如果您尝试使用具有更高内存量的 GPU,您应该能够设置更大的堆大小。
编辑 v1:如果您的卡具有更高的 RAM,您可以尝试从主机代码动态分配 ,超过 1024 MB 的缓冲区?如果你不能这样做,那可能是驱动程序的限制。
问题已通过安装 CUDA 7.0 版本解决。