发送非常大的数组时,Cuda Memory Functions会出现“Unknown Error”

时间:2012-08-15 19:22:43

标签: cuda labview

我的程序分析一个视频文件,该文件表示为一个3d数组并从LabView发送到我的程序。 LabView已经将这个3d数组变成了一个1d数组,所以我刚刚在CUDA中使用cudaMalloc分配了1d数组,并使用cudaMemcpy来复制数据。但是我注意到,如果我发送超过2XXX,120x240像素图像,我从我的一些cuda内存函数(cudamemcpy和cudafree,我的程序稍后在调用几个内核后出现)中得到“未知错误”并且这最终打破了我的计划。但是,如果我降低数字,如果我发送的图像我没有问题。这让我相信我的代码很好,但我的内存分配实践很糟糕。

首先,让我们谈谈Pitched memory。据我所知,这就是选择一个好的大小来分配内存,这样线性数据就不会分成两个块。这对于2D和3d数组尤其常见,因为您希望将行或列保留在内存中以便快速访问。

如果我不使用音调内存会出现这类问题吗?不使用音调内存时会出现什么样的错误,特别是对于这些非常大的数组?到目前为止,我忽略了使用cudaMallocPitch和cudaMalloc3d的选项,尽管我在技术上有2d和3d数组,我已经扁平化了。

最后,当cudaGetLastError只告诉我“未知错误”时,如何进一步调试代码问题?我能够找到哪个函数有问题,但是当它像cudaFree一样,我没有办法调试这类东西,或者找出问题所在的位置。

无论如何,谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

不使用音调内存的成本是速度。如果两个线程试图访问视频的相邻帧并且帧被分配在连续的内存中(没有对齐),则一个帧的一部分将与另一个帧驻留在同一个内存块或缓存行中,并且一个线程可能必须等到另一个线程完成其内存操作。可能不是致命的,但绝对不是最佳的。那里可能还有写后读或写后写问题。

使用带内存的成本是,如果元素(帧或扫描线)大小不是首选对齐边界的偶数倍,它将略微增加内存分配。下一帧或扫描线的开始可能必须填充几个字节,以使其在适当的存储器地址边界上开始。向每个帧或扫描线大小添加30个字节以获得2000帧的下一个适当边界将为您的总内存分配增加大约60,000个字节。

如果总数据集不适合设备内存,则必须将数据集分成较小的块,并多次调用cuda内核来处理每个块。如果您的代码不需要随时随机访问整个数据集,那么切换到流模型可能会大大减少您的整体处理时间。当一个warp正在等待其数据块加载到设备内存中时,另一个warp可以处理其块,因此CUDA内核不会处于空闲状态。

如果您的视频处理代码需要查看4个连续的帧缓冲区来完成其工作,那么您可以设计一个缓冲区管理系统,该系统在不再需要时从队列中退出最旧的帧并设置新帧准备下一次内核调用。更好的是 - 为新帧回收旧的帧存储器,以避免内存分配的开销。

仅在您实际需要时(或之前)加载您需要的内容。这是20美元的视频播放器和录像机芯片以实际RAM的微薄实时处理数千兆字节视频流的方式。