JCuda - Java bindings für CUDA

Und nochmal - vielleicht interessiert es ja hier jemanden:

Die Version 0.1.1 (alpha!) von JCuda, einer Java-Anbindung für die Runtime- und Driver API von CUDA gibt es jetzt auf http://www.jcuda.org .

Mit der Runtime-Anbindung kann man die Bibliotheken ansprechen, die es auch auf http://www.jcuda.org gibt:
[ul]
[li]JCublas: Java bindings für CUDA BLAS, die CUDA-Implementierung der “Basic Linear Algebra Subprograms”
[/li][li]JCufft: Java bindings für CUDA FFT, die CUDA-Implementierung der Fast Fourier Transformation
[/li][li]JCudpp: Java bindings für CUDPP, die CUDA Data Parallel Primitives Library
[/li][/ul]

Mit der Driver-API kann man selbst erstellte CUBINs laden und die kernel ausführen.

Die binaries gibt es im Moment nur als 32bit-Windows-Versionen, aber jeder kann sich die Bibliotheken für seine Kombination aus Betriebssystem und Hardware-Architektur selbst compilieren.

Insbesondere die Driver APU ist noch nicht ausführlich getestet - speziell bei streams, events und memory alignment gibt es noch ein bißchen was zu tun. Aber vielleicht hat ja jemand hilfreiche Vorschläge zur Verbesserung.

bye

Hmm, OK. Aber ich kann damit nix anfangen… Wozu braucht man das?

Ach so. Hmja.

Mit CUDA kann man (ganz allgemein) Berechnungen mit der Grafikkarte durchführen. Also nicht mit dem Hauptprozessor, der CPU, sondern mit dem Prozessor auf der Grafikkarte, der GPU.

Die Motivation dafür? Ganz einfach: :smiley:

Mit CUDA kann man Programme schreiben, die z.B. 10000 (zehntausend) Threads quasi-parallel ausführen, und das Erstellen und verwalten dieser Threads ist … effektiv kostenlos.

Besonders lohnt sich das natürlich bei Aufgaben, die sich entsprechend gut parallelisieren lassen - und Lineare-Algebra-Operationen und Fast Fourier Transformationen gehören dazu. Wenn man also mal in die Verlegenheit kommt, eine Rechnung wie
C = a * A * B + b * C
für skalare (float) Werte a und b, und 1000x1000-Matrizen A,B und C durchführen zu müssen (also eine klassische BLAS-Aufgabe) dann hat man zwei Möglichkeiten: Man schreibt das ganze „brute force“ auf und läßt es die CPU berechnen. Mit einigen Tricks und Kniffen schafft man es dann vielleicht noch, das 5% schneller zu machen, oder auch 10% oder 50%. Die andere Möglichkeit ist, dass man das stattdessen mit JCublas (d.h. CUBLAS) auf der Grafikkarte ausrechnen läßt - wie in diesem Vergleich - dann geht es nichtmehr darum, es mit viel Aufwand 50% schneller zu machen, sondern darum, es mit wenig Aufwand 50 MAL schneller zu machen.

Bei Fast Fourier Transforms ist der Unterschied etwas weniger dramatisch, aber es gibt viele Fälle wo JCufft da immernoch deutlich schneller ist als eine reine Java-Implementierung (siehe auch einige Benchmarks hier).

Einen Array mit ints zu sortieren ist mit JCudpp zwar dann schon nicht mehr viel schneller als mit Arrays.sort, aber CUDPP ist eher als eine Bibliothek mit utility-Funktionen gedacht, die bei parallelen Berechnungen häufig gebraucht werden - d.h. wenn man etwas sortieren will, was ohnehin schon auf der Grafikkarte liegt (und man den Speicher nicht erst extra von Java über C auf die Grafikkarte und dann wieder zurück schaufeln muss) lohnt sich das natürlich.

Und schließlich kann man auch noch eigene Kernel mit CUDA schreiben - also die Berechnungen, die man gerade für sein Problem durchführen muss, von 10000 Threads auf 200 Prozessoren ausführen lassen - und das ganze dann von Java aus starten. Bei welchen Anwendungen sich das lohnen könnte, sieht man auf der CUDA Homepage - an den speedup-faktoren, die jeweils rechts unten in der Ecke stehen.

Und warum hast Du Dich für CUDA entschieden wo es doch OpenCL gibt welches auch von nVidea unterstützt wird (wobei sie CUDA als Bridge nehmen werden) und gleichenfalls ATI?
Bin selber gerade dabei mich in OpenCL einzufinden, noch ist die Unterstützung mager, und CUDA/PhysX ist da schon weit verbreiteter, aber mit OpenCL hat man gleich wieder einen Standard wie bei OpenGL. Mit CUDA bin ich auch schon in Kontakt gekommen aber mehr um Unterschiede zu recherchieren.

Gut Schuß
VuuRWerK :wink:

„Das hat sich so ergeben“ :wink: Vor etwa 2 Jahren wollte ich mal schauen, ob man sowas wie „JCuda“ schreiben kann - da war OpenCL - überspitzt formuliert - noch das Glitzern im Auge eines verrückten Apple-Programmierers :wink: . Ich habe dann aber schnell gemerkt, dass das nicht (so einfach) in der Form möglich sein würde, wie ich es ursprünglich gedacht hätte, und habe darum „erstmal“ JCublas implementiert, dann JCufft… dann lange nichts, dann wollte ich noch „JCudpp“ schreiben, und habe das dann auch gemacht, aber eben gleich mit JCuda als eine Anbindung von Java an die CUDA driver- und runtime-API kombiniert. (Meine ursprüngliche Idee … ist im Moment auch nicht viel mehr als ein Glitzern im Auge… aber auch „in Arbeit“)

OpenCL ist natürlich auch schon eine Weile auf meinem Radar. Nur… auf http://www.khronos.org/developers/resources/opencl/ steht nur, dass man doch bitteschön was dazu beitragen soll, auf http://www.nvidia.com/object/cuda_opencl.html muss man sich für das „Early Access Program“ registrieren, und bei ATI findet man auch nur Pressemeldungen und Ankündigungen… :confused: Woraus besteht denn dein „einfinden in OpenCL“ bisher…?

OpenCL wird natürlich noch von keiner Grafikkarte unterstützt, denn die Spezifikation wurde ja erste Ende letzen Jahres verabschiedet. Jetzt gilt es diesen Standard zu implementieren und anzubieten. Mein „einfinden in OpenCL“ beschränkt sich daher leider auch nur im studieren der Spezifikation (http://www.khronos.org/registry/cl/specs/opencl-1.0.43.pdf) und Header-Files (http://www.khronos.org/registry/cl/).

Es wäre jedoch möglich für OpenCL die Java-Bindings schon zu entwickeln da die Spec steht, daher hatte ich gefragt. Aber gut, wenn Du schon etwas länger dran sitzt ist es natürlich klar das Du Dich für CUDA entschieden hast welches schon weitaus länger aufm Markt ist.

Und das „klitzern in Deinen Augen“ ist was genau? Gleich eine Erweiterung für die VM? Denn sowas wie CUDA/OpenCL in pure Java kann man ja getrost knicken :slight_smile:

Gut Schuß
VuuRWerK :wink:

Ja, die Spec und die Header stehen schon - und wegen gewisser Ähnlichkeiten zu CUDA sind bestimmte Entwicklungen … ja, schon arg naheliegend … werde zwar kurzfristig nicht sooo viel Zeit haben, aber … sooo aufwändig ist das ja im Idealfall auch garnicht :rolleyes: Ich schreib’ dir mal 'ne PN.

Es gibt jetzt JCuda 0.2, mit Unterstützung für CUDA 2.2 und OpenGL/JOGL-Interoperability. Dazu auch mal ein kleiner Screenshot:

Ein Gitter aus 512x512 Punkten, die in einem Vertex Buffer Object gespeichert sind, mit JOGL gezeichnet werden und mit JCuda mit einer sin*cos-Welle animiert werden. Dabei kommt der gleiche Kernel zum Einsatz, wie auch im nativen „Simple OpenGL“ Beispiel von der NVIDIA Webseite. Mit JCuda läuft das ganze auf meiner GeForce 8800 GT mit 130 FPS, während es im Plain-Java-Modus auf meinen Quad Core 2.4GHz mit gemächlichen 13 FPS läuft.

Hier natürlich auch noch :wink:

Es gibt ein Update auf JCuda 0.2.1.

Die wichtigste Erweiterung ist die Möglichkeit, Exceptions einzuschalten. Normalerweise liefern die Funktionen von CUDA und den verwandten Bibliotheken nur einen Fehlercode - und teilweise noch nicht einmal das. Unter C behilft man sich darum mit Utility-Funktionen und Makros, die den Fehlercode automatisch abfragen und ggf. mit einer Fehlermeldung abbrechen. Bei JCuda gibt es jetzt die Methode
JCuda.setExceptionsEnabled(true);
(analog dazu bei JCudaDriver, JCublas, JCufft und JCudpp). Wenn Exceptions damit eingeschaltet sind, wird eine CudaException geworfen, sobald eine (native) Funktion etwas anderes zurückgeben will als den jeweiligen „success“-Code. Wenn Exceptions ausgeschaltet sind, haben die Funktionen das original-Verhalten der jeweiligen CUDA-Funktionen.

Zusätzlich sind noch einige kleinere Punkte bei der Driver-API hinzugekommen - im wesentlichen Konstanten für Texturaddressierungsmodi, die vorher gefehlt haben.

Auf der Webseite gibt es jetzt auch eine Übersichtsseite zu den Code Samples.

Hier noch ein kleiner Screenshot von einer der Beispielanwendungen: Dieses Programm liest den Volumendatensatz für ein Buckminster-Fulleren aus einer RAW-Datei, kopiert das ganze in eine 3D-Textur, rendert die 3D-Textur mit dem CUDA-Kernel als dem „volumeRender“-Beispiel von der NVIDIA Webseite in ein Pixel Buffer Object, und zeigt das Pixel Buffer Object dann mit JOGL an.

Feedback ist natürlich immer erwünscht :slight_smile:

Es gibt ein kleines Update. Ein paar kleinere Änderungen und Bugfixes, Project-Files für 64bit Windows, und jetzt auch Build-Files für für Linux und MacOS (letzteres konnte ich aber kaum testen). Wie immer unter http://jcuda.org/