2016-06-19 6 views
8

Ich beginne gerade Julias CUDArt-Paket zu verwenden, um GPU-Computing zu verwalten. Ich frage mich, wie ich sicherstellen kann, dass, wenn ich gehe, um Daten von der GPU zu ziehen (z. B. unter Verwendung von to_host()), dass ich dies nicht tue, bevor alle notwendigen Berechnungen daran durchgeführt worden sind.Synchronisieren mit Julia CUDArt?

Durch einige Experimente scheint es, dass to_host(CudaArray) verzögert wird, während das bestimmte CudaArray aktualisiert wird. Also, vielleicht reicht das nur aus, um die Sicherheit zu gewährleisten? Aber es scheint ein bisschen chancy.

Momentan verwende ich die launch() Funktion, um meine Kernel auszuführen, wie im Paket documentation dargestellt.

Die CUDArt-Dokumentation gibt ein Beispiel mit Julias @sync Makro, das scheint, als könnte es schön sein. Aber für die Zwecke von @sync bin ich fertig mit meiner "Arbeit" und bereit, weiterzugehen, sobald der Kernel mit launch() gestartet wird, nicht sobald es fertig ist. So weit ich die Operation von launch() verstehe - gibt es keine Möglichkeit, diese Funktion zu ändern (z. B. um zu warten, dass sie die Ausgabe der Funktion erhält, die sie "startet").

Wie kann ich eine solche Synchronisation erreichen?

Antwort

1

ich denke, die mehr kanonische Weg ist, einen Strom für jedes Gerät zu machen:

streams = [(device(dev); Stream()) for dev in devlist]

und dann innerhalb des @async Blockes, nachdem Sie ihm sagen, um die Berechnungen zu tun, verwenden Sie die wait(stream) Funktion Sag ihm, dass er warten soll, bis der Stream seine Berechnungen beendet hat. Siehe das Streams-Beispiel in der README.

+0

Guter Punkt. Ich denke, 'device_synchronize' kann immer noch in einer Reihe von Einstellungen nützlich sein. 1. Sie können es zusammen mit anderen Funktionen wie CUBLAS, CUSPARSE usw. verwenden, die keine Streams als Argumente verwenden. Wenn Sie nur mit einer einzigen GPU arbeiten, benötigen Sie möglicherweise nicht einmal Streams, und so kann 'device_synchronize' zu ​​etwas einfacheren Anwendungen führen. –

10

Ok, also, es gibt nicht eine Tonne Dokumentation über das CUDArt-Paket, aber ich habe mir den Quellcode angeschaut und ich denke, es sieht einfach aus, wie man das macht. Insbesondere scheint es, dass es eine device_synchronize() Funktion gibt, die blockiert wird, bis alle Arbeiten am gerade aktiven Gerät beendet sind. So scheint insbesondere Folgendes zu arbeiten:

using CUDArt 
md = CuModule("/path/to/module.ptx",false) 
MyFunc = CuFunction(md,"MyFunc") 
GridDim = 2*2496 
BlockDim = 64 
launch(MyFunc, GridDim, BlockDim, (arg1, arg2, ...)); 
device_synchronize() 
res = to_host(arg2) 

Ich würde allerdings mit mehr Know-how von jemandem zu hören lieben, wenn es irgendetwas von hier mehr zu beachten ist.

+7

Nur ein Wort der Vorsicht: undokumentierte Funktionen können für den internen Gebrauch da sein (daher der Mangel an Dokumentation). Natürlich ist das nicht immer der Fall, aber wenn Sie diese Funktionen verwenden, können Sie sich beim Upgrade auf die nächste Version auf Ärger einstellen. Paket- und Bibliothekseigentümer neigen dazu, sich leichter damit anzufreunden, nicht dokumentierte Features zu modifizieren oder direkt zu entfernen, selbst zwischen kleineren Releases. Seien Sie vorsichtig und schreiben Sie Regressionstests. – JDB