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

时间:2016-11-10 01:41:46

标签: cuda out-of-memory jcuda

我在使用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的内存,所以我不知道为什么我的内存不足。有没有人对此有任何想法?我使用JCuda 0.8.0RC和CUDA 8的发布版本确实如此,但我尝试下载RC版本的CUDA 8(8.0.27)以与JCuda 0.8.0RC一起使用让它发挥作用的一些问题。但是,如果版本兼容性可能会成为问题,我可以再试一次。

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

1 个答案:

答案 0 :(得分:2)

<强> TL; DR:

致电

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类型。这是针对“任意”大小的特定于实现的 unsigned 整数类型。 Java中最接近的原始类型是long。通常,CUDA中的每个size_t都映射到JCuda中的long。在这种情况下,Java long作为jlong传递到JNI层,这只是为了实际的本机调用而转换为size_t

(Java中缺少无符号类型和C中奇数过多的整数类型仍然会导致问题。有时,C类型和Java类型不匹配。但只要分配不大于9百万兆字节(!),long在这里应该没问题......)

但是comment by havogt导致了正确的轨道。这里发生的事情 确实是整数溢出:实际值的计算

110000 * 5000 * Sizeof.FLOAT = 2200000000
默认情况下,

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

使用long值进行计算时,通过显式转换为long或将L后缀附加到其中一个文字,该值将作为正确值传递给CUDA long值为2200000000.