JNI vs. JNA-Leistung

Lesezeit: 4 Minuten

Wir haben einen Eingeborenen c/asm Anwendung mit GPU (OpenCL) für eine große encrypt/decrypt Daten mit einer bestimmten Methode, und es funktioniert einfach perfekt, kein Problem. Ein Teil des Projekts (Web und Distribution) wird von entwickelt JEEund wir müssen nur die native Anwendung/Bibliothek aufrufen.

Wir haben versucht, es als getrennt-externen Prozess unter Verwendung zu bezeichnen Process Klasse. Das Problem ist, dass wir die Anwendung nicht steuern können (Ereignis, Handler, Threads usw.). Wir haben auch versucht, den C-Code einfach in Java-Code umzuwandeln, aber die Leistung ist gestorben. Abgesehen davon, dass ich den nativen Code als Prozess ausführe, denke ich über JNA und JNI nach, aber es gibt einige Fragen.

Fragen:

  1. Für eine bessere (schnellere) Lese-/Schreiblösung ist es möglich, Daten über direkten (nicht verwalteten) Speicher auszutauschen [Java(ByteBuffer#allocateDirect())] in JNI und JNA?
  2. Ist es möglich, den Prozess durch nativen Code zu verwalten und zu handhaben und über Java-Code (OpenCL lib) auf den (gemeinsam genutzten) GPU-Speicher zuzugreifen?
  3. Was ist mit der Leistung? Ist JNA schneller als JNI?

Wir haben zwei geclusterte AMD W7000-Geräte auf Redhat Linux6 x64.

Benutzeravatar von Peter Lawrey
Peter Lawrey

JNA ist viel langsamer als JNI, aber viel einfacher. Wenn die Leistung kein Problem darstellt, verwenden Sie JNA.

Die Verwendung direkter Puffer hat den Vorteil, dass die kritischsten Operationen kein JNI oder JNA verwenden und daher schneller sind. Sie verwenden intrinsische, wenn bedeutet, dass sie in einzelne Maschinencode-Anweisungen umgewandelt werden.

Wenn Java-Code erheblich langsamer als C ist, wurde der Code wahrscheinlich nicht ausreichend optimiert. Im Allgemeinen sollte die GPU die ganze Arbeit erledigen. Wenn Java also etwas langsamer ist, sollte dies keinen großen Unterschied machen.

Wenn Sie zB 99 % der Zeit in der GPU verbringen und Java doppelt so lange braucht, ist die Gesamtzeit 99 + 2 % oder 1 % langsamer.

  • Danke Kumpel zu viel. Nun, wir haben so viel versucht, den C-Code auf Java umzustellen, aber außer GPGPU haben wir einige Probleme wie die Verwendung von AVX-, AES- und MMX-Erweiterungen. und es ist interessant, dass JNA langsamer als JNI ist. Wir hatten einige einfache Tests, die uns sagten, dass JNA schneller ist. Sie haben Recht, wir müssen uns mehr Zeit für Java nehmen. Danke Kumpel 😀

    Benutzer2889419

    10. März 2014 um 15:20 Uhr

  • Zu Ihrer Information, JavaCPP ist so einfach zu verwenden wie JNA, aber so schnell wie reines JNI.

    – Samuel Audet

    30. August 2014 um 7:27 Uhr

Aus Offizielle FAQ von JNA:

Wie ist die Leistung von JNA im Vergleich zu benutzerdefiniertem JNI?

Die direkte JNA-Zuordnung kann eine Leistung bieten, die der von benutzerdefiniertem JNI nahekommt. Nahezu alle Typzuordnungsfunktionen der Schnittstellenzuordnung sind verfügbar, obwohl die automatische Typkonvertierung wahrscheinlich etwas Overhead verursachen wird.

Der Aufrufaufwand für einen einzelnen nativen Aufruf mit JNA-Schnittstellenzuordnung kann um eine Größenordnung (~ 10-mal) länger sein als bei entsprechendem benutzerdefiniertem JNI (ob dies im Kontext Ihrer Anwendung tatsächlich der Fall ist, ist eine andere Frage). Grob ausgedrückt liegt der Aufruf-Overhead in der Größenordnung von Hunderten von Mikrosekunden anstelle von Dutzenden von Mikrosekunden. Beachten Sie, dass dies der Anruf-Overhead ist, nicht die gesamte Anrufzeit. Diese Größenordnung ist typisch für den Unterschied zwischen Systemen, die dynamisch gepflegte Typinformationen verwenden, und Systemen, bei denen Typinformationen statisch kompiliert werden. JNI kodiert Typinformationen fest im Methodenaufruf, wobei die JNA-Schnittstellenzuordnung Typinformationen zur Laufzeit dynamisch bestimmt.

Sie können eine Beschleunigung von etwa einer Größenordnung erwarten, wenn Sie zu JNA Direct Mapping wechseln, und einen Faktor von zwei oder drei, wenn Sie von dort zu benutzerdefiniertem JNI wechseln. Der tatsächliche Unterschied variiert je nach Verwendung und Funktionssignaturen. Wie bei jedem Optimierungsprozess sollten Sie zuerst feststellen, wo Sie eine Geschwindigkeitssteigerung benötigen, und dann sehen, wie viel Unterschied es gibt, indem Sie gezielte Optimierungen durchführen. Die Leichtigkeit, alles in Java zu programmieren, wiegt normalerweise kleine Leistungssteigerungen bei der Verwendung von benutzerdefiniertem JNI auf.

Ich habe eine einfache DLL entwickelt und eine leere Funktion eingefügt, die nichts tut. Dann habe ich diese Funktion von dll mit JNA und auch JNI aufgerufen, also habe ich versucht, die Kosten für den Aufruf zu berechnen. Bei der Betrachtung der Leistung nach vielen Aufrufen war JNI 30- bis 40-mal schneller als JNA.

Die schwere Zahlenverarbeitung erfolgt in C/GPU, alles, was Ihre Java <--> C-Schnittstelle tut, ist das Mischen von Daten. Ich wäre überrascht, wenn dies ein Engpass ist.

Schreiben Sie auf jeden Fall den einfachsten und klarsten Code, der die Aufgabe erfüllt. Wenn sich herausstellt, dass die Leistung nicht ausreicht, messen wo die Engpässe sind, und gehen Sie einen nach dem anderen an, bis die Leistung in Ordnung ist. Programmiererzeit ist viel wertvoller als Computerzeit, abgesehen von ganz besonderen Umständen.

1395890cookie-checkJNI vs. JNA-Leistung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy