0

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

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

如果我不使用音高记忆,会不会出现这些问题?不使用倾斜内存时会出现哪些错误,尤其是对于这些非常大的数组?到目前为止,我忽略了使用 cudaMallocPitch 和 cudaMalloc3d 的选项,尽管我在技术上确实有 2d 和 3d 数组,我已经将它们展平了。

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

无论如何,感谢您的帮助。

4

1 回答 1

2

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

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

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

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

仅在您真正需要时(或之前)加载您需要的内容。这就是 20 美元的视频播放器和录像机芯片如何用少量的实际 RAM 实时处理数 GB 的视频流。

于 2012-08-15T21:35:49.110 回答