Frage an image-processing, cuda, image, c++, convolution – CUDA kleine Kernel 2d Faltung - wie es geht

13

Ich habe tagelang mit CUDA-Kernel experimentiert, um eine schnelle 2D-Faltung zwischen einem 500x500-Bild (ich könnte aber auch die Abmessungen variieren) und einem sehr kleinen 2D-Kernel (einem Laplace-2D-Kernel, also einem 3x3-Kernel) durchzuführen einen großen Vorteil mit allen cuda Threads zu nutzen).

Ich habe eine klassische CPU-Implementierung erstellt (zwei für Schleifen, so einfach wie man denkt) und dann habe ich begonnen, CUDA-Kernel zu erstellen.

Nach ein paar enttäuschenden Versuchen, eine schnellere Faltung durchzuführen, kam ich zu folgendem Code:http://www.evl.uic.edu/sjames/cs525/final.html (siehe Abschnitt "Shared Memory"). Ein 16x16-Thread-Block lädt im Grunde alle Faltungsdaten, die er benötigt, in den Shared Memory und führt dann die Faltung durch.

Nichts, die CPU ist noch viel schneller. Ich habe den FFT-Ansatz nicht ausprobiert, da das CUDA-SDK angibt, dass er bei großen Kernelgrößen effizient ist.

Unabhängig davon, ob Sie alles gelesen haben, was ich geschrieben habe, lautet meine Frage:

Wie kann ich mit CUDA eine schnelle 2D-Faltung zwischen einem relativ großen Bild und einem sehr kleinen Kernel (3x3) durchführen?

Ich brauche momentan kein Timing, ich kann sehen, dass das Programm mit der CPU VIEL schneller fertig wird :( paulAl
Was meinst du mit "die CPU ist noch viel schneller"? Planen Sie das vollständige Programm einschließlich des Kopierens des Speichers zur und von der GPU oder nur die Zeit, die der Kernel zum Starten und Fertigstellen benötigt? Brendan Wood

Deine Antwort

1   die antwort
9

dass der 3x3-Kernel nicht für einen FFT-basierten Ansatz geeignet ist. Der beste Weg, um damit umzugehen, wäre, den Kernel in einen konstanten Speicher zu verschieben (oder wenn Sie eine fermi + -Karte verwenden, sollte dies nicht allzu wichtig sein).

Da Sie die Kernelgröße kennen, besteht die schnellste Möglichkeit darin, Teile des eingegebenen Bildes / Signals in den gemeinsamen Speicher zu lesen und eine nicht gerollte Multiplikations- und Additionsoperation durchzuführen.

-

Wenn Sie Bibliotheken verwenden möchten, um diesen Vorgang auszuführenArrayFire undOpenCV haben hochoptimierte Faltungsroutinen, mit denen Sie viel Entwicklungszeit sparen können.

Ich bin nicht sehr vertraut mit OpenCV, aber in ArrayFire können Sie Folgendes tun.

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

BEARBEITEN

Der zusätzliche Vorteil der Verwendung von ArrayFire liegt in der Stapelverarbeitung, mit der Sie die Faltung parallel durchführen können. Sie können nachlesen, wie Faltungen Stapeloperationen unterstützenHier

Wenn Sie beispielsweise 10 Images hatten, die Sie mit demselben Kernel zusammenführen möchten, können Sie Folgendes tun:

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

-

Vollständige Offenlegung: Ich arbeite bei AccelerEyes und arbeite aktiv an ArrayFire.

Die Links sind tot. Um die Verletzung zusätzlich zu beleidigen, wurde das Wayback Machine-Archiv explizit gelöscht:accelereyes.com/robots.txt Hjulle
@Hjulle Wir haben von Accelereyes zu Arrayfire umbenannt. Die Links führten für mich zu unserer aktuellen Dokumentation. Es tut mir leid, wenn Sie Probleme hatten. Ich habe den Code und die Links aktualisiert, um die neueste Version von arrayfire wiederzugeben. Pavan Yalamanchili
@Hjulle Ich kann den direkten Link für gpu :: Convolve nicht finden, aber ich habe auf die Bildverarbeitungsseite verwiesen, auf der es um Faltung geht. Pavan Yalamanchili
Es tut mir leid, wenn ich genervt klang, danke. Die OpenCV-Verbindung ist jedoch immer noch unterbrochen. Hjulle

Verwandte Fragen