CUDA 小内核 2d 卷积 - 如何做
CUDA small kernel 2d convolution - how to do it
我已经尝试了几天的 CUDA 内核,以便在 500x500 图像(但我也可以改变尺寸)和非常小的 2D 内核(拉普拉斯 2d 内核,所以它是一个 3x3 内核......太小而无法利用所有 CUDA 线程的巨大优势)之间执行快速 2D 卷积)。
我创建了一个 CPU 经典实现(两个 for 循环,就像你想象的一样简单),然后我开始创建 CUDA 内核。
在几次令人失望的尝试执行更快的卷积之后,我最终得到了以下代码:http://www.evl.uic.edu/sjames/cs525/final.html(参见共享内存部分),它基本上允许 16x16 线程块加载他需要的所有卷积数据到共享内存中,然后执行卷积。
没什么,CPU还是快很多的。我没有尝试 FFT 方法,因为 CUDA SDK 声明它对大内核大小是有效的。
无论你是否阅读我写的所有内容,我的问题是:
如何使用 CUDA 在相对较大的图像和非常小的内核 (3x3) 之间执行快速 2D 卷积?
你是对的,因为 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的另一个好处是它的批处理操作允许您并行执行卷积。您可以在此处阅读卷积如何支持批处理操作的信息
例如,如果您有 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。
- 具有可分离内核的 2D 模糊卷积
- CUDA 使用共享内存平铺 3D 卷积实现
- OpneCV - 保留十进制的卷积
- C++中复向量与实向量的二维卷积
- 如何在张量流上使用 fp16(Eigen::half) 进行卷积
- 如何在卷积程序的 c++ 中优化嵌套循环
- 带有多通道内核的图像卷积
- 在 Caffe 中,如何修改特定卷积层的行为?
- 使用膨胀卷积的语义分割中的上采样
- 使用 OpenCL 进行图像卷积中的参数大小无效
- C++的全卷积网络训练
- 卷积二维与深度卷积二维计算
- 优化的图像卷积算法
- 我没有从使用 FFTW 的重叠添加 FFT 卷积中获得预期结果
- 卷积:卷积中的最后一个元素永远不会正确
- 如何在Caffe中对复发性卷积神经网络进行建模
- 如何在C 中而不是Prototext中启动卷积层
- 使用高斯模糊进行图像卷积,可以加速
- 自定义Caffe Windows CPP中的卷积层
- CUDA 小内核 2d 卷积 - 如何做