web-dev-qa-db-fra.com

Performances des Java?

Nous calculons quelque chose dont l'exécution est liée par des opérations matricielles. (Quelques détails ci-dessous si cela vous intéresse.) Cette expérience a conduit à la question suivante:

Les gens ont-ils de l'expérience avec les performances de Java pour les mathématiques matricielles (par exemple, multiplier, inverser, etc.)?

J'ai cherché et rien trouvé.


Détails de notre comparaison de vitesse:

Nous utilisons Intel FORTRAN (ifort (IFORT) 10.1 20070913). Nous l’avons réimplémenté dans Java (1.6) en utilisant les opérations matricielles Math 1.2 d’Apache commons maths et il accepte tous ses chiffres de précision. (Nous avons des raisons de le vouloir en Java.) doubles, Fortran réel * 8). Fortran: 6 minutes, Java 33 minutes, même ordinateur. Le profilage jvisualm indique le temps passé en beaucoup dans RealMatrixImpl. {getEntry, isValidCoordinate} (qui semble avoir disparu) Apache commons math 2.0 2.0, mais 2.0 n’est pas plus rapide) Fortran utilise les routines BLAS d’Atlas (dpotrf, etc.).

Évidemment, cela pourrait dépendre de notre code dans chaque langue, mais nous pensons que la plupart du temps se fait en opérations matricielles équivalentes.

Dans plusieurs autres calculs qui n'impliquent pas de bibliothèques, Java n'a pas été beaucoup plus lent, et parfois beaucoup plus rapide.

146
dfrankow

Juste pour ajouter mes 2 cents. J'ai comparé certaines de ces bibliothèques. J'ai essayé de multiplier matricielle une matrice de doubles de 3000 par 3000 avec elle-même. Les résultats sont les suivants.

En utilisant ATLAS multithread avec C/C++, Octave, Python et R, le temps pris était d’environ 4 secondes.

En utilisant Jama avec Java, le temps pris était de 50 secondes.

En utilisant Colt et Parallel Colt avec Java, le temps pris était de 150 secondes!

En utilisant JBLAS avec Java, le temps pris était de nouveau d'environ 4 secondes, JBLAS utilisant ATLAS multithread.

Donc, pour moi, il était clair que les bibliothèques Java ne fonctionnaient pas très bien. Toutefois, si quelqu'un doit coder en Java, la meilleure option est JBLAS. Jama, Colt et Parallel Colt ne le sont pas. vite.

96
Hamaad Shah

Je suis l'auteur de Java Matrix Benchmark ( JMatBench )) et je vais donner mon avis sur cette discussion.

Il y a une différence significative entre les bibliothèques Java et bien qu’il n’y ait pas de vainqueur clair sur l’ensemble des opérations, il existe quelques leaders clairs, comme on peut le voir dans le derniers résultats de performance (octobre 2013).

Si vous travaillez avec de "grandes" matrices et pouvez utiliser des bibliothèques natives, le gagnant clair (environ 3,5 fois plus rapide) est [~ # ~] mtj [~ # ~] avec netlib optimisé par le système . Si vous avez besoin d’une solution Java pure), alors [~ # ~] mtj [~ # ~] , OjAlgo , [~ # ~] ejml [~ # ~] et Les colonnes parallèles sont un bon choix. Pour les petites matrices, EJML est le grand gagnant.

Les bibliothèques que je n'ai pas mentionnées présentaient des problèmes de performances importants ou manquaient de fonctionnalités clés.

109
lessthanoptimal

Je suis l'auteur principal de jblas et je tiens à préciser que j'ai publié la version 1.0 à la fin du mois de décembre 2009. J'ai beaucoup travaillé sur l'emballage, ce qui signifie que vous pouvez désormais télécharger un "gros pot" avec les bibliothèques ATLAS et JNI. pour Windows, Linux, Mac OS X, 32 et 64 bits (sauf pour Windows). De cette façon, vous obtiendrez la performance native en ajoutant simplement le fichier jar à votre chemin de classe. Vérifiez-le à http://jblas.org !

49
Mikio Braun

Jeigen https://github.com/hughperkins/jeigen

  • enveloppe la bibliothèque Eigen C++ http://eigen.tuxfamily.org , qui est l'une des bibliothèques C++ libres les plus rapides disponibles
  • syntaxe relativement concise, par exemple 'mmul', 'sub'
  • gère les matrices denses et clairsemées

Un test rapide, en multipliant deux matrices denses, à savoir:

import statique jeigen.MatrixUtil. *;

int K = 100;
int N = 100000;
DenseMatrix A = Rand(N, K);
DenseMatrix B = Rand(K, N);
Timer timer = new Timer();
DenseMatrix C = B.mmul(A);
timer.printTimeCheckMilliseconds();

Résultats:

Jama: 4090 ms
Jblas: 1594 ms
Ojalgo: 2381 ms (using two threads)
Jeigen: 2514 ms
  • Par rapport à jama, tout est plus rapide :-P
  • Par rapport aux jblas, Jeigen n’est pas aussi rapide, mais il gère des matrices clairsemées.
  • Par rapport à ojalgo, Jeigen prend à peu près la même quantité de temps, mais utilise un seul cœur. Jeigen utilise donc la moitié de la quantité totale de processeurs. Jeigen a une syntaxe de testeur, c'est-à-dire 'mmul' contre 'multiplyRight'
8
Hugh Perkins

Je viens de comparer Apache Commons Math avec jlapack.

Test: décomposition en valeurs singulières d’une matrice aléatoire 1024x1024.

Machine: Processeur E6750 @ 2,66 GHz Intel® Core (TM) 2 Duo, Linux x64

Code d'octave: A = Rand (1024); tic; [U, S, V] = svd (A); toc

 résultats temps d'exécution 
 ----------------------------------------- -------------------- 
 Octave 36.34 sec 
 
 JDK 1.7u2 64bit 
 Jlapack dgesvd 37.78 sec 
 Apache commons math SVD 42.24 sec 
 
 
 JDK 1.6u30 64bit 
 jlapack dgesvd 48.68 sec 
 Apache commons math SVD 50.59 sec 
 
 Routines natives 
 Lapack * invoqué depuis C: 37.64 sec 
 Intel MKL 6.89 sec (!) 

Ma conclusion est que jlapack appelé à partir de JDK 1.7 est très proche des performances binaires natives de lapack. J'ai utilisé la bibliothèque binaire lapack fournie avec la distribution linux et appelé la routine dgesvd pour obtenir les matrices U, S et VT. Tous les tests ont été effectués en double précision sur exactement la même matrice à chaque exécution (sauf Octave).

Déni de responsabilité - Je ne suis pas un expert en algèbre linéaire, je ne suis affilié à aucune des bibliothèques ci-dessus et ce n'est pas un critère rigoureux. Il s’agit d’un test "fait maison", car j’ai été intéressé de comparer l’augmentation des performances de JDK 1.7 à 1.6 ainsi que celle de SVD math commun à jlapack.

8
isti_spl

Je ne peux pas vraiment commenter des bibliothèques spécifiques, mais en principe, il y a peu de raisons pour que de telles opérations soient plus lentes en Java. Hotspot fait généralement ce que vous attendez d'un compilateur: il compile les opérations mathématiques de base sur Java variables en instructions machine correspondantes (il utilise SSE instructions, mais seulement une par opération); les accès aux éléments d’un tableau sont compilés de manière à utiliser les instructions "brutes" MOV comme vous le souhaiteriez; il prend les décisions relatives à la façon dont les variables sont attribuées aux registres quand il le peut; tirer parti de l'architecture du processeur ... Une exception possible est que, comme je l'ai mentionné, Hotspot n'exécutera qu'une opération par instruction SSE; vous pouvez en principe disposer d'une bibliothèque de matrices optimisée de manière fantastique qui effectue plusieurs opérations par instruction, bien que je ne sache pas si, par exemple, votre bibliothèque FORTRAN particulière existe ou si une telle bibliothèque existe. Sinon, il n’existe actuellement aucun moyen pour Java (ou du moins , Hotspot) pour rivaliser avec cela (bien que vous puissiez bien sûr écrire votre propre bibliothèque native avec ces optimisations appeler depuis Java).

Donc qu'est-ce que tout cela veut dire? Bien:

  • en principe, il vaut la peine de chercher une bibliothèque plus performante, bien que je ne puisse malheureusement pas en recommander une
  • si les performances sont vraiment essentielles pour vous, je considérerais simplement de coder vos propres opérations matricielles, car vous pourrez alors effectuer certaines optimisations qu’une bibliothèque ne peut généralement pas, ou qu’une bibliothèque particulière que vous utilisez ne fonctionne pas (si vous avez un machine multiprocesseur, savoir si la bibliothèque est réellement multithread)

Un obstacle aux opérations de la matrice réside souvent dans les problèmes de localisation des données qui surviennent lorsque vous devez parcourir ligne par ligne et colonne par colonne, par exemple. dans la multiplication matricielle, puisque vous devez stocker les données dans un ordre qui optimise l’un ou l’autre. Mais si vous écrivez le code à la main, vous pouvez parfois combiner des opérations pour optimiser la localité des données (par exemple, si vous multipliez une matrice par sa transformation, vous pouvez transformer une traversée de colonne en une traversée de ligne si vous le souhaitez. écrire une fonction dédiée au lieu de combiner deux fonctions de bibliothèque). Comme d'habitude dans la vie, une bibliothèque vous donnera des performances non optimales en échange d'un développement plus rapide. vous devez décider à quel point la performance est importante pour vous.

7
Neil Coffey

Il existe un benchmark de divers packages matriciels disponible dans Java à partir de http://code.google.com/p/Java-matrix-benchmark/ pour un certain nombre de configurations matérielles, mais cela ne remplace pas votre propre test de performance.

Les performances varient en fonction du type de matériel dont vous disposez (processeur, cœurs, mémoire, cache L1-3, vitesse du bus), de la taille des matrices et des algorithmes que vous souhaitez utiliser. Différentes bibliothèques ont des interprétations différentes de la simultanéité pour différents algorithmes. Il n'y a donc pas de réponse unique. Vous pouvez également constater que le temps système nécessaire à la traduction du formulaire attendu par une bibliothèque native annule l’avantage en termes de performances pour votre cas d’utilisation (certaines bibliothèques Java ont des options plus souples en matière de stockage matriciel, qui peuvent être utilisé pour d’autres optimisations de performances).

De manière générale, JAMA, Jampack et COLT vieillissent et ne représentent pas l’état des performances actuelles disponibles dans Java pour l’algèbre linéaire. Des bibliothèques plus modernes permettent une utilisation plus efficace de plusieurs cœurs et processeurs. JAMA était une implémentation de référence et implémentait plus ou moins les algorithmes de manuel sans se soucier des performances. COLT et IBM Ninja étaient les premières bibliothèques Java) pour montrer que les performances étaient possibles en Java, même si 50% derrière les bibliothèques natives.

6
culana

Je suis l'auteur de la bibliothèque la4j (Algèbre linéaire pour Java) et voici ce que je veux dire. Je travaille sur la4j depuis 3 ans (la dernière version est la 0.4.0 [01 juin 2013]) et ce n'est que maintenant que je peux commencer à effectuer des analyses et des optimisations de performances, car je viens juste de couvrir le minimum fonctionnel requis. Donc, la4j n'est pas aussi rapide que je le voulais mais je passe beaucoup de temps à le changer.

Je suis actuellement en train de porter la nouvelle version de la4j sur la plate-forme JMatBench . J'espère que la nouvelle version affichera de meilleures performances que la précédente, car plusieurs améliorations ont été apportées à la4j, telles qu'un format de matrice interne beaucoup plus rapide, des accesseurs non sécurisés et un algorithme de blocage rapide pour les multiplications matricielles.

4

Avez-vous jeté un œil à Intel Math Kernel Library ? Il prétend surpasser même ATLAS . MKL peut être tilisé en Java via les wrappers JNI.

3
Zach Scrivena

Nous avons utilisé COLT pour des calculs financiers assez importants et nous en sommes très satisfaits. Dans notre code très profilé, nous n'avons presque jamais eu à remplacer une implémentation COLT par une des nôtres.

Dans leurs propres tests (évidemment pas indépendants), je pense qu'ils prétendent dans un facteur de 2 des routines d'assembleur optimisées manuellement d'Intel. L'astuce pour bien l'utiliser est de s'assurer que vous comprenez leur philosophie de conception et d'éviter toute attribution d'objet superflue.

3
Nick Fortescue

Le code Linalg qui s'appuie fortement sur les capacités de calcul vectoriel des processeurs Pentiums et ultérieurs (à commencer par les extensions MMX, comme LAPACK et désormais Atlas BLAS) n'est pas "optimisé de manière fantastique", mais simplement standard. Pour reproduire cette performance dans Java, vous allez avoir besoin de bibliothèques natives. J'ai eu le même problème de performances que vous avez décrit (principalement pour pouvoir calculer les décompositions de Choleski) et rien trouvé de vraiment efficace. : Jama est du pur Java, car il est supposé être juste un gabarit et un kit de référence à suivre par les implémenteurs ... ce qui ne s’est jamais produit. compter beaucoup sur les améliorations de Ninja, dont la plupart ont été atteintes en construisant un compilateur ad-hoc Java, je doute donc que cela va aider. À ce stade, je pense que nous avons simplement besoin d'un effort collectif pour construire une implémentation native de Jama ...

2
Varkhan

Vous voudrez peut-être consulter le projet jblas . Il s’agit d’une bibliothèque relativement nouvelle Java) qui utilise BLAS, LAPACK et ATLAS pour des opérations matricielles hautes performances.

Le développeur a posté quelques benchmarks dans lesquels jblas se dégage favorablement contre MTJ et Colt.

2
Mark Reid

S'appuyant sur l'article de Varkhan, le code natif spécifique à Pentium ferait mieux:

2
dfrankow

Pour les applications graphiques en 3D, la mise en œuvre du vecteur lwjgl.util surclasse les jblas mentionnés ci-dessus d’un facteur 3 environ.

J'ai effectué 1 million de multiplications matricielles d'un vec4 avec une matrice 4x4.

lwjgl fini en 18ms environ, jblas nécessitait environ 60ms.

(Je suppose que l’approche JNI n’est pas très appropriée pour l’application successive rapide de multiplications relativement petites. En effet, la traduction/mappage peut prendre plus de temps que l’exécution réelle de la multiplication.)

2
Necrowizzard

Il y a aussi UJMP

1
Chad Okere

Vous devriez ajouter Apache Mahout à votre liste de magasinage.

0
bmargulies

Matrix Tookits Java (MTJ) a déjà été mentionné auparavant, mais il vaut peut-être la peine de le mentionner encore pour quiconque trébuche sur ce fil. Pour ceux que cela intéresse, il semblerait que MTJ remplace le linalg bibliothèque dans le Apache commons math 2.0 2. , bien que je ne sois pas sûr de la progression de ces derniers temps.

0
Steve Lianoglou

J'ai constaté que si vous créez beaucoup de matrices de grande dimension, vous pouvez rendre Jama environ 20% plus rapide si vous le modifiez pour utiliser un tableau à une dimension au lieu d'un tableau à deux dimensions. En effet, Java ne prend pas en charge les tableaux multidimensionnels de manière aussi efficace. En d’autres termes, il crée un tableau de tableaux.

Colt le fait déjà, mais j’ai trouvé que c’était plus compliqué et plus puissant que Jama, ce qui explique peut-être pourquoi les fonctions simples sont plus lentes avec Colt.

La réponse dépend vraiment de ce que vous faites. Jama ne supporte pas une fraction des choses que Colt peut faire et qui font plus de différence.

0
Peter Lawrey

Il existe de nombreuses bibliothèques gratuites Java algèbre linéaire. http://www.ujmp.org/Java-matrix/benchmark/ Malheureusement, cette référence ne vous donne que des informations sur la multiplication de matrices (la transposition du test ne permet pas aux différentes bibliothèques d'exploiter leurs caractéristiques de conception respectives).

Ce que vous devriez regarder, c'est comment se comportent ces bibliothèques d'algèbre linéaire lorsqu'on leur demande de calculer diverses décompositions matricielles. http://ojalgo.org/matrix_compare.html

0
Anders Peterson