CUDA 小核 2d 卷积 - 怎么做
Posted
技术标签:
【中文标题】CUDA 小核 2d 卷积 - 怎么做【英文标题】:CUDA small kernel 2d convolution - how to do it 【发布时间】:2012-04-26 02:10:13 【问题描述】:我几天来一直在试验 CUDA 内核,以在 500x500 图像(但我也可以改变尺寸)和非常小的 2D 内核(拉普拉斯 2d 内核,因此它是 3x3 内核)之间执行快速 2D 卷积。 . 太小而无法利用所有 cuda 线程获得巨大优势)。
我创建了一个 CPU 经典实现(两个 for 循环,就像您想象的那样简单),然后我开始创建 CUDA 内核。
经过几次令人失望的尝试执行更快的卷积后,我最终得到了以下代码: http://www.evl.uic.edu/sjames/cs525/final.html(参见共享内存部分),它基本上让一个 16x16 线程块将他需要的所有卷积数据加载到共享内存中,然后执行卷积。
没什么,CPU 还是快了很多。我没有尝试 FFT 方法,因为 CUDA SDK 声明它对大内核大小有效。
无论你是否阅读了我写的所有内容,我的问题是:
如何使用 CUDA 在相对较大的图像和非常小的内核 (3x3) 之间执行快速 2D 卷积?
【问题讨论】:
“CPU 仍然快很多”是什么意思?您是在计时整个程序,包括将内存复制到 GPU 或从 GPU 复制内存,还是只计时内核启动和完成所需的时间? 我现在不需要计时,我可以看到带有 CPU 的程序完成得更快:( 【参考方案1】:你说得对,3x3 内核不适合基于 FFT 的方法。处理这个问题的最好方法是将内核推送到常量内存中(或者如果您使用的是 fermi+ 卡,这应该没什么大不了的)。
由于您知道内核大小,因此最快的方法是将输入图像/信号的块读取到共享内存中并执行展开的乘法和加法运算。
--
如果您愿意使用库来执行此操作ArrayFire 和OpenCV 具有高度优化的卷积例程,可以为您节省大量开发时间。
我对 OpenCV 不太熟悉,但是在 ArrayFire 中您可以执行以下操作。
array kernel = array(3, 3, h_kernel, afHost); // Transfer the kernel to gpu
array image = array(w, h, h_image , afHost); // Transfer the image to gpu
array result = convolve2(image, kernel); // Performs 2D convolution
编辑
使用 ArrayFire 的另一个好处是它的批处理操作允许您并行执行卷积。您可以阅读有关卷积如何通过here 支持批处理操作的信息
例如,如果您有 10 个图像要使用相同的内核进行卷积,您可以执行以下操作:
array kernel = array(3, 3, h_kernel, afHost); // Transfer the kernel to gpu
array images = array(w, h, 10, h_images, afHost); // Transfer the images to gpu
array res = convolve2(images, kernel); // Perform all operations simultaneously
--
完全披露:我在 AccelerEyes 工作并积极致力于 ArrayFire。
【讨论】:
链接已失效。雪上加霜,他们的 Wayback Machine 档案已被明确清除:accelereyes.com/robots.txt @Hjulle 我们从 acceleyes 更名为 arrayfire。这些链接正在为我重定向到我们当前的文档。如果您遇到问题,我很抱歉。我更新了代码和链接以反映最新版本的 arrayfire。 如果我听起来很生气,我很抱歉,谢谢。不过,OpenCV 链接仍然断开。 @Hjulle 我似乎找不到 gpu::Convolve 的直接链接,但我链接到讨论卷积的图像处理页面。以上是关于CUDA 小核 2d 卷积 - 怎么做的主要内容,如果未能解决你的问题,请参考以下文章
怎么在c++的平台下用opencv做一个对图像的卷积?????
python实现卷积神经网络卷积层Conv2D实现(带stridepadding)
奉献pytorch 搭建 CNN 卷积神经网络训练图像识别的模型,配合numpy 和matplotlib 一起使用调用 cuda GPU进行加速训练