2014-01-25 7 views
6

Ich arbeite an einem Projekt, das viel OpenCL-Code benötigt. Ich verwende OpenCVs OCL-Modul, um mein Projekt schneller zu entwickeln, aber es sind einige Funktionen nicht implementiert und ich muss meinen eigenen OpenCL-Code schreiben.Daten von Mat/oclMat zu cl_mem übertragen (OpenCV + OpenCL)

Meine Frage ist das: Was ist die schnellste und billigste Möglichkeit, Daten von Mat und/oder oclMat zu einem cl_mem-Array zu übertragen. Um dies neu zu formulieren, gibt es eine gute Möglichkeit, Daten von oclMat oder Mat zu übertragen oder in die Warteschlange zu stellen (clEnqueueWriteBuffer)?

Momentan verwende ich eine for-Schleife, um Daten von Mat zu lesen (oder von oclMat herunterzuladen und dann for-Schleifen zu verwenden) und dann in die Warteschlange zu stellen. Dies stellt sich als kostspielig heraus, daher meine Frage.

Dank an alle, die diese Frage :)

+0

Hallo, hier ist etwas, das für mich funktionierte. Angenommen, x ist ein mit "1" initialisierter oclMat. oclMat x (100, 100, CV_32FC1, Skalar (1)); clSetKernelArg (Kernel, 0, sizeof (cl_mem), (void *) & x.data); Dies funktionierte für mich und ich bekam diese Idee, indem ich den OCL-Code in OpenCV durchforstete. Bitte lassen Sie es mich wissen, wenn Sie denken, dass hier etwas schief gehen könnte. Vielen Dank!! – ponderingfish

+0

Das ist der richtige Weg, es zu benutzen. Sie verwenden nicht einmal einen anderen Puffer, sondern direkt den ursprünglichen oclMat-Puffer. Seien Sie vorsichtig, das ursprüngliche oclMat nicht zu verwenden, während Sie seinen Puffer für andere Zwecke verwenden. – DarkZeros

+0

Danke @DarkZeros! – ponderingfish

Antwort

1

berechnen Speicherbandbreite, erreicht in Host-Gerät Verbindungen sieht.

Wenn Sie ~ 60% und mehr der maximalen Bandbreite erhalten, haben Sie nichts zu tun, Speicherübertragung ist so schnell wie es sein kann. Wenn Ihre Bandbreitenergebnisse jedoch niedriger als 55% - 60% des theoretischen Maximums sind, versuchen Sie, mehrere Befehlswarteschlangen mit Entsperrungsoperationen zu verwenden (vergessen Sie nicht, am Ende zu synchronisieren). Achten Sie auch auf die durchschnittliche Bildgröße. Kleine Datenübertragungen haben normalerweise einen hohen Aufwand.

Wenn Ihr Gerät gemeinsam genutzten Speicher verwendet, verwenden Sie Speicherzuordnung anstelle von Lese-/Schreibzugriff. Dies kann erheblich Zeit sparen. Wenn das Gerät über einen eigenen Speicher verfügt, wenden Sie die gepinnte Speichertechnik an, die im NVIDIA OpenCL Best Practices Guide ausführlich beschrieben wird.

+0

Vielen Dank für Ihre Antwort und Zeit! Etwas anderes funktionierte für mich - bitte überprüfe meinen Kommentar zu der ursprünglichen Frage. – ponderingfish

+0

Die Verwendung des entsprechenden Konstruktors bedeutet, dass das Kopieren unter die Haube geht. Ich nehme an, dass das Flag CL_MEM_COPY_HOST_PTR in der Speicherobjekt-Erzeugungsstufe verwendet wird. Obwohl, wenn Sie mit der Lösung zufrieden sind, das ist gut :) –

1

Die Dokumentation von oclMat heißt es, dass es irgendeine Art von Funktionalität der zugrunde liegenden ocl Pufferdaten:

//! pointer to the data(OCL memory object) 
uchar *data; 

Wenn Sie clMat bereits im Gerät haben, können Sie einfach eine Kopie Puffer von clMat.data ausführen können, um Ihre clBuffer. Aber Sie müssen ein wenig um den Speicher hacken, einige private Mitglieder des oclMat Zugriff

So etwas wie:

clEnqueueCopyBuffer(command_queue, (clBuffer *)oclMat.data, dst_buffer, 0, 0, size); 

HINWEIS: Achten Sie darauf, mit dem Gießen, vielleicht müssen Sie einen anderen Zeiger werfen.

+0

Vielen Dank für Ihre Antwort und Zeit! Etwas anderes funktionierte für mich - bitte überprüfe meinen Kommentar zu der ursprünglichen Frage. – ponderingfish

2

Ich habe eine Reihe von Interop-Funktionen für die Boost.Compute-Bibliothek geschrieben, die die Verwendung von OpenCL und OpenCV erleichtern. Schauen Sie sich die opencv_copy_mat_to_buffer() Funktion an.

Es gibt auch Funktionen zum Kopieren von einem OpenCL-Puffer zurück zum Host cv::Mat und zum Kopieren von cv::Mat zu OpenCL image2d Objekten.

0

Für Ihren Kommentar ist es richtig. Das oclMat kann als cl_mem (void *) für das Gerät verwendet werden, da es vom OpenCL-Gerät zugewiesen wurde.

Zusätzlich können Sie zuerst svm-Speicher erstellen (zum Beispiel void * svmdata) und dann eine Mat wie Mat A (Zeilen, Spalten, CV_32FC1, svmdata) zuweisen. Jetzt können Sie die Mat A zwischen Host und Gerät ohne Speicherkopie verarbeiten. (PS. Der svm-Speicher ist das neue Zeichen von OCL, kann von CLSVMAlloc erstellt werden).

Verwandte Themen