C++ CUDA小内核2d卷积-怎么做

C++ CUDA小内核2d卷积-怎么做,c++,image,image-processing,cuda,convolution,C++,Image,Image Processing,Cuda,Convolution,我已经用CUDA内核进行了几天的实验,在500x500图像(但我也可以改变尺寸)和非常小的2D内核(拉普拉斯2D内核,所以是3x3内核..太小了,无法利用所有CUDA线程的巨大优势)之间执行快速2D卷积 我创建了一个CPU经典实现(两个for循环,就像你想的那样简单),然后我开始创建CUDA内核 在进行了几次令人失望的快速卷积尝试后,我最终得到了以下代码: (参见共享内存部分),它基本上允许16x16线程块加载共享内存中所需的所有卷积数据,然后执行卷积 没什么,CPU还是快得多。我没有尝试FFT

我已经用CUDA内核进行了几天的实验,在500x500图像(但我也可以改变尺寸)和非常小的2D内核(拉普拉斯2D内核,所以是3x3内核..太小了,无法利用所有CUDA线程的巨大优势)之间执行快速2D卷积

我创建了一个CPU经典实现(两个for循环,就像你想的那样简单),然后我开始创建CUDA内核

在进行了几次令人失望的快速卷积尝试后,我最终得到了以下代码: (参见共享内存部分),它基本上允许16x16线程块加载共享内存中所需的所有卷积数据,然后执行卷积

没什么,CPU还是快得多。我没有尝试FFT方法,因为CUDASDK声明它对于大内核大小是有效的

无论你是否阅读了我写的所有内容,我的问题是:


如何使用CUDA在相对较大的图像和非常小的内核(3x3)之间执行快速2D卷积?

您是对的,3x3内核不适合基于FFT的方法。处理这一问题的最佳方法是将内核推入恒定内存(或者如果您使用的是费米+卡,这应该不会太重要)

因为您知道内核大小,所以最快的方法是将输入图像/信号的块读入共享内存,并执行展开的乘法和加法操作

--

如果您愿意使用库来执行此操作 具有高度优化的卷积例程,可以节省大量开发时间

我不太熟悉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的附加好处是它的批处理操作允许您并行执行卷积。您可以阅读有关Convolutions如何支持跨平台的批处理操作的内容

例如,如果您有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
--


全面披露:我在AccelerYes工作,并积极参与ArrayFire工作。

你所说的“CPU仍然快得多”是什么意思?您是在为整个程序计时,包括将内存复制到GPU或从GPU复制内存,还是只为内核启动和完成所需的时间计时?我现在不需要计时,我可以看到使用CPU的程序完成得更快:(链接已死亡。雪上加霜的是,它们的Wayback机器存档已被明确清除:@Hjulle我们将accelereyes重新命名为arrayfire。这些链接正在为我重定向到我们当前的文档。如果您遇到问题,我很抱歉。我已更新代码和链接以反映arrayfire的最新版本。如果我听起来很生气,谢谢。OpenCV链接仍然断开。@Hjulle我似乎找不到gpu::Convolve的直接链接,但我链接到了讨论卷积的图像处理页面。