在GTX1080上使用大约2.2GB的内存后,CUDA内存不足消息



我正在使用JCuda,版本0.8.0RC与CUDA 8.0在GTX1080 GPU上做矩阵乘法。我将两个矩阵A和B以行长向量形式加载到设备中,并从设备中读取乘积矩阵。但我发现我用完设备内存的时间比我预期的要早。例如,如果矩阵A的维度为100000 * 5000 = 5亿个条目= 2GB的浮点值,则:

cuMemAlloc(MatrixA, 100000 * 5000 * Sizeof.FLOAT); 

工作好。但是,如果我将行数或行数从100000增加到110000,则会在此调用中得到以下错误(这是在为矩阵B和C分配内存之前进行的,因此这些不是问题的一部分):

Exception in thread "main" jcuda.CudaException: CUDA_ERROR_OUT_OF_MEMORY
at jcuda.driver.JCudaDriver.checkResult(JCudaDriver.java:344)
at jcuda.driver.JCudaDriver.cuMemAlloc(JCudaDriver.java:3714)
at JCudaMatrixMultiply.main(JCudaMatrixMultiply.java:84) (my code)

问题是,在设备上分配这种大小的矩阵应该只占用大约2.2GB,而GTX1080有8GB的内存,所以我不明白为什么我的内存不足。有人对此有什么看法吗?确实,我正在使用CUDA 0.8.0RC与CUDA 8的发布版本,但我试图下载CUDA 8(8.0.27)的RC版本与JCuda 0.8.0RC一起使用,并且有一些问题让它工作。但是,如果版本兼容性可能是问题,我可以再试一次。

100000 * 5000的矩阵当然是相当大的,在我的神经网络项目中,我不需要在一段时间内使用更大的矩阵,但我想确信我可以在这个新卡上使用所有8GB的内存。谢谢你的帮助。

tl;

调用

cuMemAlloc(MatrixA, (long)110000 * 5000 * Sizeof.FLOAT); 
//                     ^ cast to long here

cuMemAlloc(MatrixA, 110000L * 5000 * Sizeof.FLOAT); 
//                        ^ use the "long" literal suffix here

它应该工作。


cuMemAlloc的最后一个参数类型为size_t。这是一个特定于实现的无符号整数类型,用于"任意"大小。在Java中最接近的可能的基本类型是long。通常,CUDA中的每个size_t都映射到JCuda中的long。在这种情况下,Java long作为jlong传递到JNI层,并且对于实际的本机调用,它只是被转换为size_t

(Java中缺少无符号类型和C中过多的整数类型仍然会导致问题。有时候,C类型和Java类型不匹配。但只要分配不超过900万tb (!), long在这里应该没问题…)

但是havogt的评论是正确的。这里发生的情况是确实是一个整数溢出:

110000 * 5000 * Sizeof.FLOAT = 2200000000

在Java中默认使用 int 类型完成,这就是发生溢出的地方:2200000000大于Integer.MAX_VALUE。结果将是一个值。当它在JNI层中被转换为(无符号)size_t值时,它将变成一个大得离谱的值,这显然会导致错误。

当使用long值进行计算时,通过显式转换为long或通过将L后缀附加到其中一个字面量,该值作为适当的long值2200000000传递给CUDA。

相关内容

  • 没有找到相关文章

最新更新