8 Stimmen

Java-Leistung bei numerischen Algorithmen

Ich bin neugierig auf die Leistung von numerischen Java-Algorithmen, z. B. die Multiplikation von Matrizen mit doppelter Genauigkeit, die auf den neuesten JIT-Maschinen ausgeführt werden, z. B. im Vergleich zu manuell getunten SSE-C++/Assembler- oder Fortran-Pendants.

Ich habe im Internet nachgeschaut, aber die meisten Ergebnisse stammen von vor fast 10 Jahren, und soweit ich weiß, hat sich Java seither stark weiterentwickelt.

Wenn Sie Erfahrung mit der Verwendung von Java für numerisch intensive Anwendungen haben, können Sie Ihre Erfahrungen mitteilen. Wie gut ist die Leistung von Java in Kerneln, in denen die Schleifen relativ kurz sind und der Speicherzugriff nicht sehr gleichmäßig ist, aber immer noch innerhalb der Grenzen des L1-Cache liegt? Wenn ein solcher Kernel mehrmals hintereinander ausgeführt wird, kann die JVM ihn dann während der Laufzeit optimieren?

感謝

2voto

mikera Punkte 103423

Ich habe einige ziemlich große und leistungsempfindliche numerische Codes in Java geschrieben (in der Regel große Arrays von Doubles).

Ich habe festgestellt, dass Java für schnelle numerische Berechnungen "gut genug" ist. Vor allem, wenn man bedenkt, dass man in der Regel ohnehin nicht an die CPU gebunden ist - Speicherlatenz und Cache-Awareness sind wahrscheinlich das größte Problem bei großen Datenmengen.

Mit handoptimiertem C/C++-Code, der spezielle vektorisierte Anweisungen usw. oder hochgradig angepasste Speicherlayouts nutzt, kann man Java jedoch immer noch schlagen. Für den schnellsten Code könnten Sie also erwägen, den Kernalgorithmus in C/C++ zu schreiben und ihn von Java aus mit JNI aufzurufen.

Ich persönlich finde, dass das Erstellen einer Abhängigkeit von nativem Code in der Regel mehr Mühe macht, als es wert ist, daher neige ich dazu, mich an den reinen Java-Ansatz zu halten.

1voto

Peter Recore Punkte 13906

Diese ist ein Link zur Programmiersprachen-Shootout-Seite für Java vs. C++, die Ihnen einen Vergleich der Geschwindigkeit von Java bei verschiedenen rechenintensiven Algorithmen bietet. Sie zeigt Ihnen auch, wie Java-Code mit der höchsten Leistung aussieht. In den meisten Fällen benötigte Java für diese wenigen spezifischen Benchmarks mehr Zeit (aber nicht mehr als das Zwei- oder Dreifache) zur Ausführung.

1voto

JulianR Punkte 15805

Dies kommt von der .NET-Seite, aber ich bin mir zu 90 % sicher, dass dies auch bei Java der Fall ist. Während das JIT einige SSE-Befehle verwendet, wo es kann, vektorisiert es derzeit Ihren Code nicht automatisch, wenn es z. B. um Matrixmultiplikationen geht. Von Hand vektorisiertes C++ mit Compiler-Intrinsics/Inline-Assembler wird hier definitiv schneller sein.

1voto

Carsten Punkte 4064

Einer der schwächsten Punkte in Java sind (native) Matrixoperationen. Dies liegt an der Natur der Java-Matrizen:

  • Sie können eine Matrix nicht als rechteckig deklarieren, d.h. jede Zeile kann eine unterschiedliche Anzahl von Spalten haben.

  • Eine Matrix ist technisch gesehen keine "Matrix aus Doubles (oder Ints, ...)", sondern ein Array aus Arrays von ... . Der große Unterschied besteht darin, dass Arrays Java-Objekte sind und Sie dasselbe Array-Objekt mehr als einer Zeile zuweisen können.

Diese beiden Eigenschaften machen viele Standard-Matrixoptimierungen für den Compiler unmöglich.

Sie können eine bessere Leistung erzielen, indem Sie eine Java-Bibliothek verwenden, die Matrizen in einem einzigen langen Array emuliert. Allerdings haben Sie den Overhead von Methodenaufrufen für alle Zugriffe.

1voto

Agoston Horvath Punkte 238

C++ wird definitiv schneller sein. Sie können sogar einige handoptimierte Bibliotheken für Ihre Zwecke haben, die Assembler-Codes für jede der großen CPUs enthalten, die es gibt. Besser kann man es nicht machen.

Anschließend können Sie es bei Bedarf mit JNI von Java aus aufrufen.

Java ist nicht für solche arithmetischen Hochleistungsberechnungen gedacht. Wenn Sie darauf angewiesen sind, würde ich empfehlen, eine geeignete Sprache auf niedriger Ebene zu wählen, um dies zu implementieren. Alternativ können Sie den leistungsspezifischen Teil in einer Sprache auf niedriger Ebene schreiben und ihn dann mit Hilfe von JNI oder einer anderen IPC-Methode mit einem Java-Frontend verbinden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X