Je suis curieux de la performance des algorithmes numériques Java, disons par exemple la multiplication de la matrice Matrix à double précision, à l'aide des dernières machines JIT par exemple, par exemple à Tunettes à main SSE C ++ / Assembleur ou contrepartie FORTRAN. P>
J'ai regardé sur le Web, mais la plupart des résultats viennent de presque 10 ans et je comprends que Java a progressé beaucoup depuis lors. P>
Si vous avez de l'expérience en utilisant Java pour des applications numériquement intensifs, pouvez-vous partager votre expérience. Aussi, comment Java fonctionne-t-elle dans les noyaux où les boucles sont relativement courtes et l'accès à la mémoire n'est pas très uniforme mais toujours dans les limites du cache L1? Si un tel noyau est exécuté plusieurs fois de suite, JVM peut-il l'optimiser pendant l'exécution? P>
merci p>
9 Réponses :
Java utilise un compilateur juste dans le temps (JIT) pour convertir le bytecode en langage de la machine natif - donc la première fois qu'il traverse un bloc de code, il sera plus lent, mais une fois que le segment est "réchauffé", les performances seront équivalentes. . En bref - la performance numérique est plutôt bonne. P>
Jit's sont bien, mais ne suffisent pas à garantir de bonnes performances numériques.
Appariant que votre meilleur pari est de le tester pour vous-même, car les performances varieront quelque peu en fonction de ce que vous faites exactement. J'ai du mal à croire que la réponse de Shane C. Mason que Java Performance sera la même que celle de la performance C ++ ou Fortran, car même C ++ et Fortran ne sont pas vraiment comparables pour certains algorithmes de calcul scientifique. p>
J'ai un code de dynamique de fluide informatique que j'ai écrit à l'aide de C ++ et que le même code est essentiellement traduit en Fortran. Je ne sais pas vraiment pourquoi encore, mais la version Fortran est environ deux fois plus rapide que la version C ++. Je suppose que avec des fonctionnalités telles que la vérification des bornes et la collecte des ordures, Java serait plus lente que les deux, mais je ne saurais pas avant d'avoir testé. p>
Avez-vous utilisé le mot-clé restreint dans votre code C ++? Les compilateurs de Fortran ne doivent pas garantir que les pointeurs de mémoire ne sont pas aliasés pendant que les compilateurs C ++ doivent supposer que la mémoire est aliasée à moins que le contraire. Quels compilateurs avez-vous utilisés? J'ai programmé mon programme en C ++ avec intrinsics et Intel Compiler est nettement plus rapide que GCC, je suppose que les instructions de commande Intel C ++ sont mieux les instructions, car l'assemblage était autrefois très similaire, à l'exception de la commande.
Je suis vaguement conscient des problèmes d'aliasing, mais je ne comprends pas assez bien, encore. Je n'ai pas encore essayé de restreindre, je n'ai pas eu le temps de passer cela, malheureusement. J'utilisais ICPC et Ifort (les deux compilateurs Intel) sur Linux avec -O3. Notez que mon point n'est pas que la performance C ++ ne peut pas correspondre à Fortran, mais que vous devez comparer les implémentations en plus des langues.
Fortran a également un modèle de numérics beaucoup plus détendu que C ++ - il est autorisé à effectuer de nombreuses optimisations de mathématiques Skanky par défaut que vous ne recevez que C / C ++ avec -ffast-math et similaire. Parfois, cela n'a pas d'importance, et parfois cela rendra vos résultats moins précis.
Ce est un lien vers la page de lancement de la langue de programmation pour Java vs C ++, qui vous donnera une comparaison de la vitesse de Java sur plusieurs algorithmes intensives de calcul. Il vous montrera également quel code Java le plus performant ressemble. Pour la plupart, pour ces quelques points de repère spécifiques, Java a pris plus de temps (mais pas plus de 2 ou 3 fois) à courir. P>
Je ne pouvais pas dire immédiatement - cette comparaison ignore-t-elle les temps d'échauffement. Java a toujours besoin d'un lot i> de premier travail avant d'atteindre la vitesse de croisière.
vrai. Si vous souhaitez rédiger un programme qui démarre, quelques calculs et s'arrête ensuite, vous ne voulez probablement pas Java. Mais si votre programme fonctionnera pendant quelques minutes, le temps de démarrage est juste du bruit. Une alternative bien sûr consiste à démarrer un processus Java et doit-il agir en tant que serveur de calcul - chaque fois que vous avez besoin d'un calcul, vous venez d'appeler une instance déjà en cours d'exécution.
@ Thorbjørn Ravn Andersen - 1) Lisez la FAQ! 2) Remarquez que les programmes fonctionnent pendant des secondes et non microsecondes! 3) Regardez les approximations d'état d'équilibre Shootout .alioth.debian.org / u64q / ... 4) Lire la FAQ! À propos de Java shootout.alioth.debian.org/u64q/faq.php#dynamic < / a>
@igouy Si vous comparez l'état d'équilibre aux résultats Java -Server, ils ne sont pas si différents.
@Peter - je sais, dis, dites Thorbjørn :-) [mais aussi vérifier les mesures présentées dans la FAQ]
Cela vient d'un côté .NET des choses, mais je suis sûr de 90% que ce soit le cas pour Java aussi. Bien que le JIT effectue une certaine utilisation des instructions SSE où il peut, il ne vectorielle actuellement pas votre code lorsque vous traitez, par exemple, des multiplications matricielles. Vectorisé à la main C ++ à l'aide de l'ensemble intrinsèque / en ligne du compilateur sera définitivement plus rapide ici. p>
Cela peut être si dépendant de ce que vous faites dans le code C ++. P>
Par exemple, utilisez-vous le GPU? edit forte> j'ai oublié Jogl, alors Java peut faire concurrence ici. P>
Êtes-vous parallélisé à l'aide de STM ou de mémoire partagée, puis Java ne peut pas rivaliser.
Pour un lien sur l'analyse de la multiplication de matrice parallèle: http: // www.cs.utexas.edu/users/plapack/papers/ipps98/ipps98.html p>
Avez-vous suffisamment de mémoire pour effectuer les calculs en mémoire, de sorte que le collecteur des ordures ne soit pas nécessaire et avez-vous peauxé le collecteur des ordures pour une performance optimale? Ensuite, Java peut être compétitif, peut-être. P>
Utilisez-vous des multicores et est-ce que le C ++ est optimisé pour profiter de cette architecture? Alors Java ne pourra pas rivaliser. P>
Utilisez-vous plusieurs ordinateurs liés ensemble, puis Java ne pourra pas être en compétition. P>
Utilisez-vous une combinaison de ceux-ci, alors cela dépendra de la mise en œuvre particulière. P>
Java n'est pas conçu pour concurrencer un programme C ++ à la main, mais le temps nécessaire pour faire le réglage, faites-vous suffisamment de calculs où cela importera? Java sera en mesure de donner une vitesse raisonnable, mais avec moins de travail que la main-à-main, mais pas une grande partie d'une amélioration de C ++ Code. P>
Vous voudrez peut-être voir s'il y a une amélioration sur Haskell ou Erlang, par exemple, sur votre C ++, car ces langues sont mieux conçues pour ce type de travail. P>
En utilisant le GPU? Comme dans, en utilisant OpenGL? Si vous utilisez JOGL Java, peut concurrencer joliment.
Vous avez raison, j'ai corrigé ma réponse, j'ai oublié que vous pouvez utiliser JOGL pour le travail GPU.
L'un des points les plus faibles de Java est (natif) des opérations matricielles. Cela est dû à la nature des matrices Java: P>
Vous ne pouvez pas déclarer une matrice à être rectangulaire, c'est-à-dire. Chaque ligne peut avoir un nombre différent de colonnes. P> li>
Une matrice n'est techniquement pas une "matrice de double (ou INTS, ...)", mais un tableau de matrices de .... La grande différence est que, puisque les matrices sont des objets Java, vous pouvez affecter le même objet de tableau à plus de 1 rangée. P> li> ul>
Ces deux propriétés font de nombreuses optimisations de matrice standard impossibles pour le compilateur. P>
Vous pourriez avoir une meilleure performance en utilisant une bibliothèque Java qui émule des matrices sur un seul ensemble long. Cependant, vous avez la surcharge des appels de méthode pour tous les accès. P>
Je pense que vous voulez dire que vous ne pouvez pas déclarer un tableau 2D à être rectangulaire. Mais vous semblez affirmer que la mise en œuvre la plus littérale et la plus simple d'une matrice de Java a des problèmes. Pourquoi serait-ce la seule mise en œuvre possible? Si ce n'est pas le cas, il n'y a pas grand chose d'une déclaration possible ici sur la «nature des matrices Java». Qu'en est-il des bitrycrogrammes Java comme Colt?
Les matrices ne sont pas toujours représentées de cette façon. Voir java.awt.image.kernel code> pour un exemple d'une matrice représentée par un tableau 1D
Le problème avec de telles bibliothèques est que tout accès à matrix est effectué par des méthodes. Les appels de méthodes sont plus lents que l'accès à la matrice en général et empêchent certaines optimisations du compilateur. Par exemple. pour (int i = 0; i
Un autre problème avec l'utilisation d'un réseau long au lieu d'un multidimensionnel est qu'il est plus facile d'exécuter le code en parallèle. Si je connais 2 parties de l'exécution, accédez à différentes lignes ou colonnes dans le tableau (à nouveau, par exemple, des boucles imbriquées), je sais qu'ils ne peuvent pas se mettre dans les autres. Il est beaucoup plus difficile pour un compilateur de connaître cela sur les opérations sur un même tableau.
C ++ sera certainement plus rapide. Vous pouvez même avoir des bibliothèques optimisées à la main pour vos besoins contenant des codes d'assemblage pour chacun des principaux processeurs. Vous ne pouvez pas aller mieux que cela. P>
Ensuite, vous pouvez utiliser JNI pour l'appeler à partir de Java, si nécessaire. P>
Java n'est pas destiné aux calculs arithmétiques de haute performance comme celui-ci. Si vous dépendez de cela, je vous recommanderais de choisir une langue appropriée et de bas niveau à mettre en œuvre cela. Ou, alternativement, vous pouvez écrire la pièce spécifique à la performance dans une langue de niveau bas, puis la connecter à une extrémité frontale Java à l'aide de JNI ou d'une autre méthode IPC. P>
Ces types de calculs vous intéressent-ils - Fast Fourier Transform, Jacobi successif sur la relaxation, l'intégration de Monte Carlo, la matrice de matrice clairsemée à Mult, la factorisation Dense Lu Matrix? P>
Ils constituent le Benchmark composite SCIMARK 2.0 que vous pouvez lancer comme applet sur votre machine . p>
Il y a aussi Versions ANSI C des programmes et un Intel Document (PDF) sur l'optimisation et la recompilation de scimark pour C ++ strong> . P>
De même, vous pouvez utiliser Suite Java Grande Forum Benchmark < / a> et Les programmes C compartiment C . < / p>
J'ai écrit un code numérique sensible raisonnablement important et sensible à la performance en Java (croquant de grandes matrices de doubles habituellement). P>
J'ai trouvé que Java sera "assez bon" pour des calculs numériques rapides. Surtout lorsque vous considérez que vous n'êtes généralement pas lié à la CPU - de toute façon - la latence de la mémoire et la sensibilisation au cache constitueront probablement votre plus gros problème pour les grands ensembles de données. P>
Cependant, vous pouvez toujours battre Java avec un code C / C ++ optimisé à la main qui profite d'instructions vectorisées spécifiques, etc. ou des dispositions de mémoire hautement personnalisées. Donc, pour le code très le plus rapide, vous pouvez envisager d'écrire l'algorithme de base en C / C ++ et de l'appeler de Java à l'aide de JNI. P>
Personnellement, je constate que la création d'une dépendance du code natif est généralement plus de problèmes que cela ne vaut donc donc j'ai tendance à rester à l'approche pure Java. p>
Votre meilleur pari est de le tester vous-même, car la comparaison avec le C ++ sera difficile, car ce sera le plus rapide et toute comparaison n'aura pas accès à votre implémentation particulière.
Note aux autres qui viennent à cette page: cette question et la majorité des réponses sont à partir de 2009. JVM est beaucoup mieux aujourd'hui que ce n'était l'habitude d'être.
Vous voudrez peut-être regarder ND4J, qui prend en charge les tableaux N-dimensionnels pour Java. nd4j.org/benchmarking.html