Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1049 connectés 

  FORUM HardWare.fr
  Programmation
  Java

  calcul mathematique simple, optimisation Java

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

calcul mathematique simple, optimisation Java

n°1926504
ztg
Posté le 24-09-2009 à 20:51:31  profilanswer
 

ci dessous le code et le temps d'execution d'un petit programme tout simple, en C et en Java
 


$ cat cr.c
#include "math.h"
#define SIZEA 1024
#define SIZEB 4096
 
static double mat[SIZEA][SIZEB];
static double var[SIZEA];
static double cor[SIZEA][SIZEA];
 
int main(int argc, char** argv) {
 
        int i,j,k,l;
        for (i=0;i<SIZEA;i++) {
                for (j=0;j<SIZEB;j++) {
                        mat[i][j]=pow(-1,i)*i/(j+1.0);
                }
        }
        for (i=0;i<SIZEA;i++) {
                double mean;
                mean = 0;
                for (j=0;j<SIZEB;j++) {
                        mean+=mat[i][j];
                }
                mean/=SIZEB;
                double variance = 0;
                for (j=0;j<SIZEB;j++) {
                        variance+=pow((mat[i][j]-mean),2);
                }
                variance/=SIZEB;
                var[i]=variance;
        }
        // calculate correlation
        for (i=0;i<SIZEA;i++) {
                for (j=0;j<SIZEA;j++) {
                        cor[i][j]=0;
                        for(k=0;k<SIZEB;k++) {
                                cor[i][j]=mat[i][k]*mat[j][k]/(SIZEB*sqrt(var[i]*var[j]));
                        }
                }
        }
        return 0;
}
$ cat cr.java
class Cr {
 
public static void main(String [] args) {
 
        double[][] mat = new double[1024][4096];
        double[] var = new double[1024];
        double[][] cor = new double[1024][1024];
 
        int i,j,k,l;
        for (i=0;i<1024;i++) {
                for (j=0;j<4096;j++) {
                        mat[i][j]=Math.pow(-1,i)*i/(j+1.0);
                }
        }
        for (i=0;i<1024;i++) {
                double mean;
                mean = 0;
                for (j=0;j<4096;j++) {
                        mean+=mat[i][j];
                }
                mean/=4096;
                double variance=0;
                for (j=0;j<4096;j++) {
                        variance+=Math.pow((mat[i][j]-mean),2);
                }
                variance/=4096;
                var[i]=variance;
        }
        // calculate correlation
        for (i=0;i<1024;i++) {
                for (j=0;j<1024;j++) {
                        cor[i][j]=0;
                        for(k=0;k<4096;k++) {
                                cor[i][j]=mat[i][k]*mat[j][k]/(4096*Math.sqrt(var[i]*var[j]));
                        }
                }
        }
}
};
 
$ gcc -lm cr.c -o cr
$ gcc --version
gcc (Debian 4.3.4-2) 4.3.4
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
$ javac cr.java
$ java -version
java version "1.6.0_0"
OpenJDK Runtime Environment (IcedTea6 1.5) (6b16-4)
OpenJDK 64-Bit Server VM (build 14.0-b15, mixed mode)
$ time ./cr
87.9u 0.0s 1:27.92 99.9% 0+0k 0+0io 0pf+0w
$ time java Cr
117.5u 46.8s 1:24.47 194.6% 0+0k 0+112io 1pf+0w
 


 
 
 
Constatations:
 
- le temps CPU user+system consomme est plus faible pour le binaire C que pour le semi-binaire Java (Java 80% plus lent)
- le temps d’execution est plus lent de 3s sur 1min30s environ avec avantage pour Java
- C a tout son temps en “user” alors que Java a une repartition 70-30 pour user et system
 
Questions:
1) Pourquoi le temps CPU C est il bien plus faible que Java? Je m’attendais a ce que Java soit un peu plus lent, le temps de convertir le .class en instructions machines, mais pas dans de telles proportions?
2) Pourquoi C consomme t’il du temps user quasi uniquement, et Java du temps user et systeme?
3) Pourquoi le temps d’execution reel de Java est il plus court malgre le temps CPU quasi 2x plus long? Mon programme n’est pas multi-thread, donc ca ne devrait pas arriver?
 
 
 
Merci
 
 
--ztg
 
 

mood
Publicité
Posté le 24-09-2009 à 20:51:31  profilanswer
 

n°1926507
sligor
Posté le 24-09-2009 à 20:57:25  profilanswer
 

Code :
  1. for(k=0;k<4096;k++) {
  2.   cor[i][j]=mat[i][k]*mat[j][k]/(4096*Math.sqrt(var[i]*var[j]));
  3. }


tu es sûr de vouloir calculer cor[i][j] 4096 fois (et d'écraser la valeur précédente à chaque fois) ?
A mon avis il manque un "+" :o


Message édité par sligor le 24-09-2009 à 20:58:46
n°1926508
ztg
Posté le 24-09-2009 à 20:58:38  profilanswer
 

il devrait y avoir un "+=" au lieu du "=", exact
 
mais a la limite ca ne change rien, vu que l'erreur est dans les deux, non?

n°1926509
sligor
Posté le 24-09-2009 à 20:59:29  profilanswer
 

par contre ça risque de démultiplier le temps de calcul :o
si les compilo sont pas cons ils ont supprimé cette boucle


Message édité par sligor le 24-09-2009 à 20:59:51
n°1926510
ztg
Posté le 24-09-2009 à 20:59:58  profilanswer
 

ce qui importe ici c'est que les deux fassent la meme chose, pas l'exactitude du calcul

n°1926511
ztg
Posté le 24-09-2009 à 21:00:16  profilanswer
 

ok je modifie et je vois si ca change

n°1926513
ztg
Posté le 24-09-2009 à 21:04:19  profilanswer
 

bon on pouvait s'y attendre, les deux executions sont plus lentes apres cette petite modif (merci sligor de l'avoir mentionnee, effectivement on aurait pu imaginer que le compilo avait optimise ca en prenant juste la 4096e valeur... mais en fait non)
 
nouveaux temps d'execution:
 

# gcc -lm cr.c -o cr && time ./cr
94.6u 0.0s 1:34.63 99.9% 0+0k 0+0io 0pf+0w
# javac cr.java && time java Cr
117.0u 47.4s 1:24.55 194.5% 0+0k 0+112io 1pf+0w


 
la question demeure

n°1926514
sligor
Posté le 24-09-2009 à 21:08:05  profilanswer
 

il sont cons ces compilateurs [:ocolor]

 

Sinon: tu as des tableau énormes (~64Mo) donc tu exploses la mémoire cache et le CPU se tourne les pouces à attendre les datas à chaque fois.
Tu effectues des calculs compliqués sqrt float & div float: le cpu se tourne les pouces en attendant la fpu. La performance de la machine impacte beaucoup plus le résultat que les optimisations de compilation


Message édité par sligor le 24-09-2009 à 21:08:18
n°1926515
ztg
Posté le 24-09-2009 à 21:09:26  profilanswer
 

un autre truc, dans la meme portion de code, je calcule k fois 4096*Math.sqrt(var[i]*var[j]) alors qu'une suffirait (en pratique je fais ca souvent pour pas faire exploser des limites hautes pour les entiers, mais ici ca a peu de sens)
 
me demande si gcc est assez intelligent pour optimiser ca, je teste

n°1926516
ztg
Posté le 24-09-2009 à 21:10:29  profilanswer
 

>sligor
 
ok ca a du sens
 
maintenant, pourquoi cette difference entre l'execution C et Java?

mood
Publicité
Posté le 24-09-2009 à 21:10:29  profilanswer
 

n°1926518
sligor
Posté le 24-09-2009 à 21:12:57  profilanswer
 

au passage: -ffast-math peut être très utile: testé et approuvé :D

n°1926519
ztg
Posté le 24-09-2009 à 21:13:55  profilanswer
 

deja teste, ca ralentit mon execution C de 5% (va savoir pourquoi)

n°1926520
sligor
Posté le 24-09-2009 à 21:16:46  profilanswer
 

tu es sûr ? chez moi je gagne presque un rapport 10 juste en ajoutant cette option :D
Quelle version de gcc au passage ?

 

gcc -lm -O3 -mfpmath=sse -msse2 cr.c -o cr -ffast-math


Message édité par sligor le 24-09-2009 à 21:16:55
n°1926522
ztg
Posté le 24-09-2009 à 21:20:39  profilanswer
 

apres modif du diviseur dans corr[i][j] (des deux cotes bien sur)
et test --fast-math (c'etait en fait un autre flag qui me donnait -5%, j'ai parle trop vite)
 
 


# gcc -lm cr.c -o cr && time ./cr
24.6u 0.0s 0:24.67 100.0% 0+0k 0+0io 0pf+0w
 
# gcc -lm -ffast-math cr.c -o cr && time ./cr
24.6u 0.0s 0:24.68 100.0% 0+0k 0+0io 0pf+0w
 
# javac cr.java && time java Cr
6.9u 1.1s 0:06.10 132.6% 0+0k 0+64io 1pf+0w
 


 
 
[:rofl]
 
je comprends plus rien :(

n°1926523
ztg
Posté le 24-09-2009 à 21:21:34  profilanswer
 

ah ouais
 


# gcc -lm -O3 -mfpmath=sse -msse2 -ffast-math cr.c -o cr && time ./cr
5.8u 0.0s 0:05.89 99.8% 0+0k 0+0io 0pf+0w

n°1926525
ztg
Posté le 24-09-2009 à 21:22:39  profilanswer
 

ca va mieux en effet

n°1926526
sligor
Posté le 24-09-2009 à 21:24:53  profilanswer
 

en fait -O3 avec -ffast-math permet à GCC de vectoriser le code
tu peux utiliser "-ftree-vectorizer-verbose=5" pour voir ce qu'il arrive à vectoriser. Mais de toute façon la boucle qui prend le plus de temps et qui est donc la plus importante est la dernière


Message édité par sligor le 24-09-2009 à 21:25:05
n°1926527
ztg
Posté le 24-09-2009 à 21:27:16  profilanswer
 

en augmentant la taille des tableaux pour avoir qqch de plus significatif:
 


# gcc -lm -O3 -mfpmath=sse -msse2 -ffast-math cr.c -o cr && time ./cr
24.5u 0.0s 0:24.61 100.0% 0+0k 0+0io 0pf+0w
# javac cr.java && time java Cr
33.6u 12.2s 0:25.05 183.3% 0+0k 0+64io 1pf+0w


 
c'est quoi tout ce temps system en Java :??:
et pourquoi 183.3%? le temps system serait il execute en // ?

n°1926528
ztg
Posté le 24-09-2009 à 21:28:07  profilanswer
 

enfin au final, Java 87% plus lent

n°1926529
ztg
Posté le 24-09-2009 à 21:32:51  profilanswer
 

questions restantes:
 
- pourquoi tant de temps CPU en plus en Java par rapport a C?
- qu'est ce que ce temps systeme?
(optionnel)
- pourquoi 64io en Java et 0 en C? pourquoi 1pf en Java et 0 en C?

n°1926530
e_esprit
Posté le 24-09-2009 à 21:38:05  profilanswer
 

A vue de nez ca ressemble à un optimisation de java (fais donc un htop pendant l'execution, tu vas comprendre).
 
D'ailleurs si tu regardes bien le rapport de time :  
C : 99.9 % (1 CPU)
Java : 194.5% (2 CPUs)
 
Après, quelle est cette optimisation...


---------------
Ce n'est point ma façon de penser qui a fait mon malheur, c'est celle des autres.
n°1926531
ztg
Posté le 24-09-2009 à 21:45:02  profilanswer
 

entre parentheses, avec -mtune=native C est encore plus rapide (1s de moins que sans)
 


# gcc -lm -O3 -mfpmath=sse -msse2 -ffast-math -mtune=native cr.c -o cr          # time ./cr
23.5u 0.0s 0:23.62 100.0% 0+0k 0+0io 0pf+0w


 
>e_esprit
 
en theorie ce calcul est parfaitement parallelisable, c'est a dire que si j'ai 8 cpu je vais quasi 8 fois plus vite
maintenant, java est 80% plus lent mais utilise 2 CPU donc bat C sur la ligne d'arrivee... mais que fait il exactement, et pourquoi?

n°1926561
cbeyls
Hail to the King, Baby
Posté le 24-09-2009 à 22:49:44  profilanswer
 

Ayayaye, encore quelqu'un qui veut comparer des pommes et des oranges...
 
Bon alors c'est simple: quand tu lances programme Java, tu lances la JVM (un énorme programme très complexe) qui à son tour lance ton programme. Tu ne peux pas comparer le temps qu'il faut pour démarrer une JVM avec le temps qu'il faut pour démarrer un programme C déjà compilé qui est nul ou presque. La JVM est lourde à charger, c'est connu.
 
Si tu veux vraiment chronométrer un temps d'exécution, tu dois mesurer le temps d'exécution de l'application en récupérant une valeur sur l'horloge système juste avant et juste après le calcul (par exemple avec System.currentTimeMillis() même si ce n'est pas le plus précis), sinon tu vas mesurer également le temps qu'il faut pour démarrer et arrêter la JVM!
 
De plus, la JVM commence par interpréter puis compile nativement les parties du code les plus fréquemment utilisées au fil du temps (compilateur JIT intelligent), ce qui veut dire que la première exécution du calcul sera plus lente que la dernière si tu en fais plusieurs. Raison pour laquelle quand on fait des benchmarks Java, il est plus "fair play" de ne pas chronométrer la première exécution du code ni même la deuxième, mais plutôt la 3e ou 4e exécution (sans arrêter la JVM entre chaque exécution bien entendu!).
 
Tu devrais alors mesurer des performances quasi semblables avec sans doute un avantage pour le code C, en particulier parce que les calculs de type racine carrée, sinus et cosinus sont plus lents en Java qu'en C.
 
Enfin sache qu'il existe un JVM client et une JVM serveur (dont la disponibilité varie d'une plate-forme à l'autre) qui peuvent offrir des performances différentes.


Message édité par cbeyls le 24-09-2009 à 22:53:25
n°1926564
sligor
Posté le 24-09-2009 à 22:53:10  profilanswer
 

faut pas délirer, sur 23s le temps de lancement de la JVM est très négligeable. De même pour le JIT, ici on execute une boucle plusieurs millions de fois


Message édité par sligor le 24-09-2009 à 22:53:20
n°1926565
cbeyls
Hail to the King, Baby
Posté le 24-09-2009 à 22:58:43  profilanswer
 

En tous cas la JVM explique les IO et le reste des différences avec le code C.
 
Effectivement si on exécute une racine carrée plusieurs millions de fois, alors que cette opération est connue pour être beaucoup plus lente en java qu'en C, ce n'est pas étonnant que ce soit très lent :)
 
Mais bon je pense que comparer du Java et du C pour savoir lequel est le "meilleur" n'a aucun sens. Comparer plusieurs JVM ou implémentations Java serait plus intéressant.
 
Tu pourrais aussi essayer le compilateur java natif GCJ versus GCC.

n°1926572
ztg
Posté le 24-09-2009 à 23:20:48  profilanswer
 

>cbeyls
 
merci pour ces explications
le but ici n'etait pas de dire "qui ou qui est le plus rapide" (ca je crois qu'on le sait) mais "qui fait quoi et comment" pour expliquer les differences
et ton post m'eclaire sur certains points :jap:

n°1926579
cbeyls
Hail to the King, Baby
Posté le 24-09-2009 à 23:36:35  profilanswer
 

Content d'avoir éclairé ta lanterne!
 
Petite remarque quand même: le C n'est pas toujours le plus rapide contrairement à ce qu'on croit. En particulier, Java peut être plus efficace que du code C pour l'allocation de mémoire, la gestion des Exceptions et autres. Et avec chaque nouvelle version de Java, les performances sont améliorées.
 
Avant de me faire démolir par les pro-C, je tiens à préciser que j'aime et utilise de nombreux langages dont le Java et le C :)

n°1926581
sligor
Posté le 24-09-2009 à 23:38:13  profilanswer
 

Quand les exceptions impactent les performances c'est qu'elle sont mal utilisées :o (valable pour n'importe quel langage)

n°1926582
Taz
bisounours-codeur
Posté le 24-09-2009 à 23:39:26  profilanswer
 

Joelf ! viens nous apprendre à parcourir une matrice !
 
(sinon je pow(x, 2) faut voir à faire soit même le * et zieuter l'asm, des fois c'est mieux).

n°1926585
ztg
Posté le 24-09-2009 à 23:43:04  profilanswer
 

question subsidiaire:
 
qu'est ce que la JVM fait avec mon kernel pendant 30% du temps cpu?

n°1926586
ztg
Posté le 24-09-2009 à 23:43:39  profilanswer
 

taz, que veux tu dire pour le parcours d'une matrice?

n°1926588
THRAK
- THR4K -
Posté le 24-09-2009 à 23:44:59  profilanswer
 

cbeyls a écrit :


[...]
 
Mais bon je pense que comparer du Java et du C pour savoir lequel est le "meilleur" n'a aucun sens. Comparer plusieurs JVM ou implémentations Java serait plus intéressant.
 
Tu pourrais aussi essayer le compilateur java natif GCJ versus GCC.


 :jap:  
 
Le type de JVM et de compilo JIT va avoir une influence non négligeable en terme d'exécution de code, l'architecture utilisée joue pas mal aussi ; à ce niveau je pense plus particulièrement aux implémentations Zero/Shark vs Cacao.
 
Aujourd'hui, en matière de JDK, l'implémentation open source OpenJDK est aussi performante (si ce n'est plus performante) que celle de chez Sun.


---------------
THRAK (def.) : 1) A sudden and precise impact moving from intention, direction and commitment, in service of an aim. 2) 117 guitars almost striking the same chord simultaneously.
n°1926591
ztg
Posté le 24-09-2009 à 23:51:24  profilanswer
 

mes tests ci-dessus sont OpenJDK+Hotspot
 
je vais regarder Zero/Shark et Cacao

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Java

  calcul mathematique simple, optimisation Java

 

Sujets relatifs
[RESOLU]Optimisation d'une requête SQL[RESOLU] Sous Eclipse l'exécution marche bien mais pas avec la comm
Cherche programmeur JAVA pour spectre sonoreProgrammer un diagramme de classe en UML avec java !!!
Java Ajax auto completionfermeture thread java
string javaAide pour Optimisation application Facebook
Uploader un fichier en javaConnexion a un Wifi en Java ?
Plus de sujets relatifs à : calcul mathematique simple, optimisation Java


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR