Hallo Jungs,
ich benutzte eine NVIDIA Grafikkarte als Co-Prozessor. Ich habe mit Visual Studio ein C Klasse geschrieben und dann eine DLL erzeugt. Diese habe ich jetzt in Labview eingebunden. Dies funktioniert auch alles super.
Jetzt zu meinem Problem:
Ich habe in Labview ein Array bereitsgestellt. Dieses Array enthält meine Daten. Wenn ich jetzt den DLL Knoten aufrufe, dann werden meine Daten aus dem PC-Speicher in den Grafikkarten Speicher kopiert. Dies dauert viel zu lange.
Daher gibt es von NVDIA eine eigene Malloc Funktion. Die normale Malloc Funktion benutzt "pageable memory". Die von NVIDA bereitgestellte Funktion benutzt "pinned memory" diese ist 2 bis 3 mal schneller als die pageable memory malloc funktion. Wie kann ich in Labview die schnelle "pinned memory" benutzen?
Ich könnte in Labview die NVIDA DLL aufrufen und dann die pinned memory malloc funktion benutzen, jedoch macht dies in Labview große Probleme. Gibt es in Labview nicht die Möglichkeit die Speicherbereitstellung auf pinned umzustellen?
(28.06.2012 15:54 )pimbolie1979 schrieb: [ -> ]Hallo Jungs,
ich benutzte eine NVIDIA Grafikkarte als Co-Prozessor. Ich habe mit Visual Studio ein C Klasse geschrieben und dann eine DLL erzeugt. Diese habe ich jetzt in Labview eingebunden. Dies funktioniert auch alles super.
Jetzt zu meinem Problem:
Ich habe in Labview ein Array bereitsgestellt. Dieses Array enthält meine Daten. Wenn ich jetzt den DLL Knoten aufrufe, dann werden meine Daten aus dem PC-Speicher in den Grafikkarten Speicher kopiert. Dies dauert viel zu lange.
Daher gibt es von NVDIA eine eigene Malloc Funktion. Die normale Malloc Funktion benutzt "pageable memory". Die von NVIDA bereitgestellte Funktion benutzt "pinned memory" diese ist 2 bis 3 mal schneller als die pageable memory malloc funktion. Wie kann ich in Labview die schnelle "pinned memory" benutzen?
Ich könnte in Labview die NVIDA DLL aufrufen und dann die pinned memory malloc funktion benutzen, jedoch macht dies in Labview große Probleme. Gibt es in Labview nicht die Möglichkeit die Speicherbereitstellung auf pinned umzustellen?
Nein!! Du kannst den Memory Manager von LabVIEW nicht einfach umbiegen, und das willst Du auch nicht. Deine Grafikkarte hat nicht genügend Speicher um ein ganzes LabVIEW Programm zu enthalten. Und wenn die Daten dann im Host nötig sind, etwa zum Darstellen als Grafik oder was auch immer muss es wieder in den Hauptspeicher kopiert werden was einen Grossteil des Performancegewinns wieder kaputt macht. Du kannst CUDA Memory benützen aber musst das kategorisch vom LabVIEW Memory trennen. Grundsätzlich solltest Du entsprechende Memorybereiche mit CUDA Funktionen anlegen und manipulieren und innerhalb von LabVIEW nur als opaque Handles (refnums) behandeln. Wenn die Daten in LabVIEW schliesslich nötig sind, musst Du einen Heapblock allozieren und mit CUDA Funktionen diese aus dem Handle in diesen Block kopieren.
Aber bevor Du Dir hier einen Bruch holst solltest Du auf NI nach einer CUDA Library suchen. Ein entsprechendes Forum ist
hier. Die haben sowas schon implementiert und als Download verfügbar, aber CUDA Memory ist immer ein spezielles Speicherobjekt in LabVIEW. Etwas anders ist nur machbar mit direkten Änderungen im LabVIEW Source Code selber und das ist nur etwas das NI tun kann. Aber grundsätzlich lässt sich damit keine Eierlegende Wollmilchsau konstruieren. Die möglichen Anwendungsgebiete sind sehr spezifisch und bedingt durch die physikalische Trennung der verschiedenen Speicherbereiche nur mit extra Aufwand zu implementieren.
Wenn Du eine komplexe mathematische Operation hast die Du ganz auf dem GPU ausführen kannst dann macht das eventuel Sinn, aber die typische LabVIEW Applikation benötigt die Daten immer auch auf dem Host fürs Display und zum Beispiel während dem Debuggen, und das dabei ständig nötige Kopieren der Daten zwischen GPU und Hostspeicher würde jeglichen Performancegewinn mehr als zunichte machen.
Dies habe ich in den Dokumenten von NVIDIA gefunden:
The runtime provides functions to allow the use of page-locked (also known as pinned) host memory (as opposed to regular pageable host memory allocated by malloc()):
cudaHostAlloc() and cudaFreeHost() allocate and free page-locked host memory;
cudaHostRegister() page-locks a range of memory allocated by malloc() (see reference manual for limitations).
Using page-locked host memory has several benefits:
Copies between page-locked host memory and device memory can be performed concurrently with kernel execution for some devices as mentioned in Section 3.2.5;
On some devices, page-locked host memory can be mapped into the address space of the device, eliminating the need to copy it to or from device memory as detailed in Section 3.2.4.3;
Das mit den Referenzen auf die Speicher habe ich in Labview noch nie gemacht. Ich kann in meiner Klasse mit den Konstruktor der Speicher mit der NVIDA Malloc FUnktion auf dem PC bereitstellen. Dann habe ich die Adresse und könnte diese dann auch an Labview übergeben. Nur weiß ich dann nicht wie ich die Daten dann da reinschreiben kann.
Die Daten bekomme ich momentan von einer National Instrument Framegrabberkarte.
Ich benutze ein 64Bit Betriebssystem, den Funktionen aus dem Link funktionieren nur für 32Bit Betriebssystem.
Hier steht das man das neue GPU Toolkit herunterladen kann. Jetzt habe ich mich eingelogt und dort gibt es kein GPU Toolkit zum Herunterladen
https://decibel.ni.com/content/docs/DOC-6064#/?page=2
Wo kann ich denn das Toolkit runterladen?
(28.06.2012 16:54 )pimbolie1979 schrieb: [ -> ]Dies habe ich in den Dokumenten von NVIDIA gefunden:
The runtime provides functions to allow the use of page-locked (also known as pinned) host memory (as opposed to regular pageable host memory allocated by malloc()):
cudaHostAlloc() and cudaFreeHost() allocate and free page-locked host memory;
cudaHostRegister() page-locks a range of memory allocated by malloc() (see reference manual for limitations).
Using page-locked host memory has several benefits:
Copies between page-locked host memory and device memory can be performed concurrently with kernel execution for some devices as mentioned in Section 3.2.5;
On some devices, page-locked host memory can be mapped into the address space of the device, eliminating the need to copy it to or from device memory as detailed in Section 3.2.4.3;
Das mit den Referenzen auf die Speicher habe ich in Labview noch nie gemacht. Ich kann in meiner Klasse mit den Konstruktor der Speicher mit der NVIDA Malloc FUnktion auf dem PC bereitstellen. Dann habe ich die Adresse und könnte diese dann auch an Labview übergeben. Nur weiß ich dann nicht wie ich die Daten dann da reinschreiben kann.
Die Daten bekomme ich momentan von einer National Instrument Framegrabberkarte.
Ich benutze ein 64Bit Betriebssystem, den Funktionen aus dem Link funktionieren nur für 32Bit Betriebssystem.
Hier steht das man das neue GPU Toolkit herunterladen kann. Jetzt habe ich mich eingelogt und dort gibt es kein GPU Toolkit zum Herunterladen
https://decibel.ni.com/content/docs/DOC-6064#/?page=2
Wo kann ich denn das Toolkit runterladen?
Das ist eine Beta wo Du Dich anmelden musst. Und das funktioniert glaube ich nur mit LabVIEW 2012 das im August rauskommt. Da die LabVIEW 2012 Beta inzwischen beendet ist weiss ich nicht ob Du Dich da noch anmelden kannst bevor LabVIEW 2012 offiziel rauskommt.
Das andere ist alles schön und gut, aber funktioniert nur wenn die entsprechende Karte das direkt im Treiber unterstützt. Im Hinblick darauf das CUDA nur eine von mehreren solchen Initiativen ist, ist das aber eher unwahrscheinlich dass jemand wie NI sich bei ihren Framegrabber Karten darauf einlässt bevor sich nicht alle Spieler im Markt auf einen einzigen Standard geeinigt haben. Und mit Standard ist dann auch gemeint dass man nicht alles bei der nächsten Chip Generation wieder über den Haufen wirft so wie das bis jetzt gegangen ist. CUDA ist inzwischen bei Version 5 und die haben die entsprechenden APIs und Methoden schon mehrere Male im Verlauf der Entwicklung auf nicht kompatible Weise geändert. Auf sowas lässt sich kein einziger industrieller Hardwarelieferant ein, da das viel zu aufwendig und zu teuer ist, für die Handvoll early Adopters die davon dann auch wirklich Gebrauch machen.
Grundsätzlich ist page locked Memory tatsächlich schneller beim Datentransfer zu Karten da man das dann direkt mit DMA transferieren kann, und jeder Kernel Treiber der DMA unterstützt verendet auch solchen Speicher, ABER es ist nicht nur unüblich um page locked Memory ausserhalb des Kernels zu benützen sondern mangels allgemein anerkannter Standards auch keine wirkliche Möglichkeit. Jede High Speed PCI Karte kommt heutzutage mit eigener DMA Engine, und entsprechend eigenen Algorithmen im Treiber. Wenn da Treiber A und B nicht genau dasselbe machen dann gibts nicht nur einfach einen Exception Dialog sondern unweigerlich einen BSOD und das sind dann doch ziemlich hässliche Sachen. Auch würde die Windows Speicherverwaltung hoffnunglos zusammenbrechen wenn jede Applikation begänne für alles page locked Speicher zu verwenden. Page locked Speicher kann nicht virtualisiert werden und wenn Du 4GB Speicher hast und 2GB davon sind page locked dann läuft gar nichts mehr auf dem Rechner ausser einem BSOD oder ähnlichem.
Du kannst zwar solchen Speicher anlegen und benützen aber wenn Du die Daten darin in LabVIEW ansprechen willst kommst Du absolut nicht darum herum den Inhalt in einen entsprechenden Heapbereich zu kopieren. LabVIEW kann und will nicht direkt mit page locked Memory Pointern arbeiten. Und die NI-IMAQ Karten soweit zu bringen dass sie mit solchen Pointern umgehen können kann nur NI, und das bedingt ziemlich umfassende Änderungen in deren Treiber. Diese Änderungen werden sie aber nicht machen bevor ATI, nVIDIA und MS sich darauf geeinigt haben dass CUDA-Stream der offizielle Standard ist. Da hat OpenCL noch fast mehr Chancen ausser dass NI sich selten auf "Open" Standards einlässt ausser sie sind selber bei der Introduktion davon massgeblich beteiligt. Es ist für NI so oder so eine Nischenangelegenheit, denn die die CUDA oder Friends verwenden kaufen kaum NI Hardware und die die NI Hardware kaufen haben CUDA entweder nicht nötig, oder aber professionele Systemsoftwareprogrammierer im Team die das ohne weiteres in die ganze Architektur integrieren.
Wie gesagt an den IMAQ Treibern kannst Du und ich nichts tun aber die Verwendung von CUDA ist durchaus möglich. Aber ohne grundlegende und tiefgehende C Programmierkenntnisse bis hinunter zu Kernelsachen geht das eher nicht auch wenn Du selber von den Kerneltreibern in CUDA, NI-IMAQ und was noch mehr völlig fern bleibts.
Meine Bilder sind so maximal 10MByte groß. Das bdeutet ich benötige nur einen page-locked memory von 10MBtye und keinen GByte. Wie kann ich denn so ein 10MByte großes Array in Labview in den Heap kopieren, so das dann der Datentransfer in die Grafikkarte deutlich schneller wird?
Kann vielleicht jemand ein kleines Beispiel posten.
Verliere ich da nicht auch wieder viel Zeit, da ich ein Kopie des Arrays erstellen muss? Wenn ich ein RAM Benchmark Tool laufen lasse dann kann ich 19GByte pro Sekunde in den RAM schreiben und ca 19GByte aus dem PC RAM lesen.
Über den PCIe Bus kann ich mit dem page-locked memory ca 12GByte in beide Richtunge übertragen. Ohne den page-locked memory schaffe ich so ca 2 bis 4GByte und das ist dann nicht wirklich viel. Da lasse ich eine menge performance auf der Strecke. Besonders da die Daten in die Grafikkarte kopiert werden müssen und die Ergebnisse müssen auch wieder zurück kopiert werden.
(29.06.2012 17:41 )pimbolie1979 schrieb: [ -> ]Meine Bilder sind so maximal 10MByte groß. Das bdeutet ich benötige nur einen page-locked memory von 10MBtye und keinen GByte. Wie kann ich denn so ein 10MByte großes Array in Labview in den Heap kopieren, so das dann der Datentransfer in die Grafikkarte deutlich schneller wird?
Kann vielleicht jemand ein kleines Beispiel posten.
Verliere ich da nicht auch wieder viel Zeit, da ich ein Kopie des Arrays erstellen muss? Wenn ich ein RAM Benchmark Tool laufen lasse dann kann ich 19GByte pro Sekunde in den RAM schreiben und ca 19GByte aus dem PC RAM lesen.
Über den PCIe Bus kann ich mit dem page-locked memory ca 12GByte in beide Richtunge übertragen. Ohne den page-locked memory schaffe ich so ca 2 bis 4GByte und das ist dann nicht wirklich viel. Da lasse ich eine menge performance auf der Strecke. Besonders da die Daten in die Grafikkarte kopiert werden müssen und die Ergebnisse müssen auch wieder zurück kopiert werden.
MoveBlock(). Such mal hier oder auf ni.com danach. Und natürlich kostet das Zeit. Aber die eierlegende Wollmilchsau gibt es auch bei Computern nicht.