Pytanie w sprawie image-processing, convolution, cuda, image, c++ – CUDA małe jądro 2d - jak to zrobić

13

Eksperymentowałem z jądrami CUDA od wielu dni, aby wykonać szybki splot 2D między obrazem 500x500 (ale mogłem również zmieniać wymiary) i bardzo małym jądrem 2D (jądro laplacian 2d, więc jest to jądro 3x3 .. zbyt małe wykorzystać przewagę wszystkich wątków cuda).

Stworzyłem klasyczną implementację procesora (dwie pętle, tak proste, jak można by pomyśleć), a następnie zacząłem tworzyć jądra CUDA.

Po kilku rozczarowujących próbach wykonania szybszego splotu skończyło się na tym kodzie:http://www.evl.uic.edu/sjames/cs525/final.html (patrz sekcja Pamięć współdzielona), zasadniczo umożliwia blokowi wątków 16x16 załadowanie wszystkich potrzebnych danych splotu w pamięci współdzielonej, a następnie wykonuje splot.

Nic, procesor jest jeszcze szybszy. Nie wypróbowałem podejścia FFT, ponieważ SDK CUDA stwierdza, że ​​jest wydajny przy dużych rozmiarach jądra.

Niezależnie od tego, czy przeczytałeś wszystko, co napisałem, moje pytanie brzmi:

jak mogę wykonać szybki splot 2D między stosunkowo dużym obrazem i bardzo małym jądrem (3x3) z CUDA?

Co rozumiesz przez „CPU jest jeszcze szybszy”? Czy synchronizujesz pełny program, w tym kopiowanie pamięci do i z GPU, czy tylko czas potrzebny na uruchomienie i ukończenie jądra? Brendan Wood
Na razie nie potrzebuję synchronizacji, widzę, że program z CPU kończy dużo szybciej :( paulAl

Twoja odpowiedź

1   odpowiedź
9

Masz rację, że jądro 3x3 nie nadaje się do podejścia opartego na FFT. Najlepszym sposobem radzenia sobie z tym byłoby przepchnięcie jądra do stałej pamięci (lub jeśli używasz karty fermi +, nie powinno to mieć większego znaczenia).

Ponieważ znasz rozmiar jądra, najszybszym sposobem na to jest odczytanie fragmentów wejściowego obrazu / sygnału do pamięci współdzielonej i wykonanie operacji rozwijania mnożenia i dodawania.

-

Jeśli chcesz użyć bibliotek do wykonania tej operacjiArrayFire iOpenCV posiadają wysoce zoptymalizowane procedury konwekcji, które pozwalają zaoszczędzić dużo czasu na programowanie.

Nie jestem zbyt zaznajomiony z OpenCV, ale w ArrayFire możesz zrobić coś takiego.

<code>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
</code>

EDYTOWAĆ

Dodatkową korzyścią z używania ArrayFire jest jego operacja wsadowa, która umożliwia równoległe wykonywanie splotu. Możesz przeczytać o tym, jak konwertyty obsługują operacje wsadowetutaj

Na przykład, jeśli masz 10 obrazów, które chcesz połączyć za pomocą tego samego jądra, możesz zrobić coś takiego:

<code>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
</code>

-

Pełne ujawnienie: Pracuję w AccelerEyes i aktywnie pracuję nad ArrayFire.

@Hjulle Nie mogę znaleźć bezpośredniego linku do gpu :: Convolve, ale połączyłem się ze stroną przetwarzania obrazu, która mówi o splocie. Pavan Yalamanchili
Przepraszam, jeśli zabrzmiałam zirytowana, dzięki. Link OpenCV jest jednak nadal uszkodzony. Hjulle
@Hjulle Zmieniliśmy nazwę z accelereyes na arrayfire. Linki przekierowywały do ​​mnie aktualną dokumentację. Przykro mi, jeśli masz problemy. Zaktualizowałem kod i linki, aby odzwierciedlić najnowszą wersję arrayfire. Pavan Yalamanchili
Linki są martwe. Aby dodać obrazę do zranienia, archiwum tych maszyn zostało wyraźnie oczyszczone:accelereyes.com/robots.txt Hjulle

Powiązane pytania