2010-02-27 6 views
11

Ma question concerne les performances de Java par rapport au code compilé, par exemple C++/fortran/assembly dans les applications numériques hautes performances. Je sais que c'est un sujet controversé, mais je cherche des réponses/exemples spécifiques. Aussi wiki de la communauté. J'ai déjà posé des questions similaires, mais je pense que je l'ai formulé de façon générale et que je n'ai pas obtenu les réponses que je cherchais.C/C++ versus Java/C# dans les applications hautes performances

La multiplication matricielle matricielle double précision, communément appelée dgemm dans la bibliothèque blas, est capable d'atteindre des performances crêtes CPU de près de 100% (en termes d'opérations flottantes par seconde).
Il y a plusieurs facteurs qui permettent d'atteindre cette performance:

  • blocage du cache, pour atteindre la localisation de mémoire maximale boucle

  • déroulant pour réduire au minimum le contrôle frais généraux

  • instructions vectorielles, telles que SSE

  • pré-chargement de la mémoire

  • garantie pas de mémoire aliasing

J'ai vu beaucoup de repères en utilisant l'assemblage, C++, Fortran, Atlas, fournisseur BLAS (cas typiques sont la matrice de dimension 512 et au-dessus). D'autre part, j'ai entendu dire que les langages/implémentations compilés en octets de principe tels que Java peuvent être rapides ou presque aussi rapides que les langages compilés en machine. Cependant, je n'ai pas vu de repères précis montrant qu'il en est ainsi. Au contraire, il semble (de ma propre recherche) que les langages compilés sont beaucoup plus lents.

Avez-vous de bons benchmarks de multiplication matricielle matricielle pour Java/C#? est-ce que le compilateur juste-à-temps (implémentation réelle, pas hypothétique) est capable de produire des instructions qui satisfont les points que j'ai listés?

Merci

en ce qui concerne la performance: chaque CPU a des performances de pointe, en fonction du nombre de processeur instructions peut exécuter par seconde. Par exemple, un processeur Intel 2 ghz moderne peut atteindre 8 milliards de double précision ajouter/multiplier par seconde, ce qui donne 8 gflops de performance maximale. Matrix matrice multiplier est l'un des algorithmes qui est capable d'atteindre une performance presque complète en ce qui concerne le nombre d'opérations par seconde, la raison principale étant un ratio plus élevé de calcul sur les opérations de la mémoire (N^3/N^2). Numéros Je suis intéressé par quelque chose sur la commande N > 500. En ce qui concerne la mise en œuvre: des détails de niveau supérieur tels que le blocage est effectué au niveau du code source. L'optimisation de niveau inférieur est gérée par le compilateur, peut-être avec des indications de compilateur en ce qui concerne l'alignement/alias. La mise en œuvre compilée en octets peut également être écrite en utilisant une approche par bloc, de sorte qu'en principe, les détails du code source pour une mise en œuvre décente seront très similaires.

+0

Je peux écrire du code en Java qui utilise 100% du CPU - même sans rien faire de sens ;-) Je suppose que je comprends ce que vous voulez vraiment dire, mais votre phrasé est un peu ambigu. –

+0

Toujours pas beaucoup plus clair pour moi ... voulez-vous dire qu'il y a une sorte de "idéal" qui stipule que pour une architecture CPU donnée la meilleure performance numérique imaginable est telle et telle, et c'est ce que vous appelez 100 pour cent? Y aurait-il une mesure concrète comme MFLOPS pour cela? Je ne suis pas un expert dans ce domaine. –

+0

Je n'ai pas voté pour fermer cet article (je n'ai même pas encore le droit). Je trouve cela intéressant, essayant seulement de vous donner des commentaires pour clarifier votre message. –

Répondre

0

Résolution du problème SSE: Java is using SSE instructions since J2SE 1.4.2.

+2

Pour autant que je sache, il n'utilise pas les instructions SSE pour vectoriser le code, ni le .NET CLR. Mono a quelques structures (vecteurs et matrices) qui sont traitées spécialement par le compilateur JIT qui est transformé en code vectorisé. – JulianR

+0

@JR c'était aussi mon impression – Anycorn

1

Tous les facteurs que vous spécifiez sont probablement effectués par une optimisation manuelle de la mémoire/du code pour votre tâche spécifique. Mais le compilateur JIT n'a pas assez d'informations sur votre domaine pour rendre le code optimal à la main, et ne peut appliquer que des règles générales d'optimisation.En conséquence, il sera plus lent que le code de manipulation de matrice C/C++ (mais peut utiliser 100% de CPU, si vous le voulez :)

+0

vrai. Mais la vectorisation, les problèmes d'aliasing sont souvent traités par les compilateurs. De plus, boucle déroulant un quelque chose que je m'attendrais à ce que le compilateur fasse. L'accès au cache est assez simple dans les langages de compilation, mais comment le langage de compilation byte le gère-t-il? – Anycorn

+0

@aaa: le moteur/compilateur JIT s'en charge. – LiraNuna

2

Comparaison de VC++/.NET 3.5/Mono 2.2 dans un scénario de multiplication matricielle pure :

http://img237.imageshack.us/img237/2788/resultse.png Source

Mono avec Mono.Simd va un long chemin à combler l'écart de performance avec le C++ optimisé main ici, mais la version C++ est encore clairement le plus rapide. Mais Mono est à 2.6 maintenant et pourrait être plus proche et je m'attendrais à ce que si .NET obtient quelque chose comme Mono.Simd, il pourrait être très compétitif car il n'y a pas beaucoup de différence entre .NET et le C++ séquentiel ici.

+0

merci. Qu'est-ce qui explique la différence entre deux implémentations SIMD? regarder dans une donnée, il semble être lié à la mémoire? – Anycorn

+1

En parlant de SSE en C++, je vous suggère de comparer également GCC 4.4, juste pour l'exhaustivité, car la génération de code SSE de MSVC est vraiment horrible (voir http://www.liranuna.com/sse-intrinsics-optimizations-in-popular- compilateurs/pour plus de détails). – LiraNuna

0

java ne peut pas rivaliser avec c dans les multiplikations matricielles, l'une des raisons est qu'il vérifie sur chaque accès au tableau si les limites du tableau sont dépassées. plus mathématique java est lente, elle n'utilise pas les processeurs sin(), cos().

Questions connexes