CUDA small kernel 2d свертка - как это сделать

я экспериментировал с ядрами CUDA в течение нескольких дней, чтобы выполнить быструю 2D-свертку между изображением 500x500 (но я также мог изменять размеры) и очень маленьким 2D-ядром (2d-ядром Лапласа, поэтому это ядро 3x3.. слишком мало, чтобы воспользоваться огромным преимуществом со всеми потоками cuda).

Я создал классическую реализацию CPU (два для циклов, как легко, как вы думаете), а затем я начал создавать ядра CUDA.

после нескольких неудачных попыток, чтобы выполните более быструю свертку, я закончил с этим кодом: http://www.evl.uic.edu/sjames/cs525/final.html (см. раздел Общая память), он в основном позволяет потокам 16x16 загружать все данные свертки, которые ему нужны в общей памяти, а затем выполняет свертку.

ничего, процессор по-прежнему намного быстрее. Я не пробовал подход FFT, потому что CUDA SDK утверждает, что он эффективен с большими размерами ядра.

читаете вы или нет все, что я написал, мой вопрос:

как я могу выполнить быструю 2D-свертку между относительно большим изображением и очень маленьким ядром (3x3) с помощью CUDA?

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 является его пакетная операция, позволяющая выполнять свертку параллельно. Вы можете прочитать о том, как convolvutions поддерживает пакетные операции над здесь

например, если у вас было 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.