IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Threads & Processus C++ Discussion :

Tentative de reduction de temps de calcul avec openMP: ECHEC


Sujet :

Threads & Processus C++

  1. #1
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Novembre 2011
    Messages : 18
    Par défaut Tentative de reduction de temps de calcul avec openMP: ECHEC
    Bonjour a tous,
    J'aurais vraiment besoin de vos lumières

    J'ai un code assez long a exécuter, j'ai donc décidé de me pencher sur la parallélisation avec openMP

    J'ai reproduit un code jouet reprenant ce que je souhaiterais paralléliser dans mon vrai code: deux calculs de la même fonction (avec paramètres différents) sur deux cœurs en même temps.

    Voila mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    #include <iostream>
    #include <iomanip>
    using namespace std;
    #include <boost/progress.hpp>
    #include<omp.h>
     
    double fct_test1(int r, int t) {
       double temp=0;
       temp = (2*r + 3*t + 200)/12;
       return temp;
    }
     
    double fct_test(int a , int b, int c, int r, int t) {
       double temp = 0;
       for (int i = 0; i < 2100000000; i++)
        {
        temp += ((a + 30*b + c*5)/(fct_test1(r,t)*100000000));
        }
       return temp;
    }
     
    int main() {
       boost::progress_timer time;
       double test = 0. ;
       double test_prop = 0. ;
     
       #pragma omp parallel
       {
        #pragma omp sections nowait
        {
           #pragma omp section
           {
             cout <<  omp_get_thread_num() << endl;
             test = fct_test(2,2,2,2,2) ;
           }
          #pragma omp section
          {
             cout << omp_get_thread_num() << endl;
             test_prop = fct_test(3,3,3,3,3) ;
          }
        }
    }
     
    cout << "test" << test << endl;
    cout << "test_prop" << test_prop << endl;
     
    return 0.;
     
    }
    Sans utiliser openMP mon code tourne en 4.22 secondes alors qu'en utilisant le code décrit ci-dessus il met 5.70 s !!!

    J'ai lu sur ce forum que l'appel des fonctions openMP est coutêux en temps, j'ai donc tenté ce type de code sur mon vrai programme (où la fonction demandée va mettre environ 20 secondes/ par réalisation) mais il se passe la même chose: les temps de calculs sont plus long...

    Peut-être n'ai-je pas bien utilisée la bibliothèque, peut être que c'est inutile de paralléliser ce type de code... je ne sais plus trop quoi faire

    Une idée ??

    Merci beaucoup,
    Nane

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Bonjour

    Sur le code que tu présentes, j'obtiens de bonnes performances avec OpenMP (un peu trop d'ailleurs).
    Je compile avec les options -O3 -march=native -fopenmp avec GCC 4.8.2.

  3. #3
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Novembre 2011
    Messages : 18
    Par défaut
    Bonjour Ehonn,
    Je viens de tester avec tes options (ajoutée aux miennes) avec une version gcc 4.4.6
    Extrait de mon makefile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    CFLAGS= -O3 -march=native -fomit-frame-pointer -Wall -pipe -funroll-loops -fno-inline
    LDFLAGS = -fopenmp
    Mais rien n'y fait le temps d'exécution est toujours lent 5.75secondes...

    Penses-tu que ce soit la bonne écriture pour paralléliser ce genre de code?

    Merci

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Il faut mettre -fopenmp dans les CFLAGS aussi, sinon ton programme reste séquentiel.
    Au passage, -fomit-frame-pointer est déjà activé avec -O.
    Pour les options -funroll-loops -fno-inline, j'aurais tendance à laisser le compilateur choisir mais c'est toi qui choisis
    Avec GCC 4.8.2, j'ai eu des soucis avec -pipe en compilant qu'un seul fichier; j'ai pas cherché plus que ça (mauvaise utilisation, manque de place, ...) mais l'exécutable généré n'était pas correct :s
    (Sinon, tu as bien une machine avec plusieurs cœurs ?)

    Pour paralléliser le code j'aurais plutôt fait un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #pragma omp parallel for reduction(+:temp)
    for (int i = 0; i < 2100000000; i++)
    {
        temp += ((a + 30*b + c*5)/(fct_test1(r,t)*100000000));
    }

  5. #5
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Novembre 2011
    Messages : 18
    Par défaut
    Je travail sur un calculateur qui a enormement de coeurs... (je ne sais plus le chiffre exact!)
    Je viens de re-tenter en modifiant le makefile : toujours les mêmes résultats.

    C'est vrai qu'en parallélisant la boucle directement, le gain de temps est réel mais ce code est un code jouet... et la fonction décrite ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (int i = 0; i < 2100000000; i++)
    {
        temp += ((a + 30*b + c*5)/(fct_test1(r,t)*100000000));
    }
    n'est pas la même que la réelle... (elle est beaucoup plus complexe en vrai!)

    Penses-tu qu'il y a un moyen de demander l’exécution de deux fonctions en même temps sur deux cœurs différents ?

  6. #6
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Et si tu lances ton exécutable (version OpenMP) comme ceci, tu obtiens quoi comme temps ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    export OMP_NUM_THREADS=1 && time ./ton_exe
    export OMP_NUM_THREADS=2 && time ./ton_exe
    export OMP_NUM_THREADS=4 && time ./ton_exe
    export OMP_NUM_THREADS=8 && time ./ton_exe

  7. #7
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Novembre 2011
    Messages : 18
    Par défaut
    Et bin pas vraiment de réponses en fait ^^ mise a part " de coder soit même les threads " !!

    Je viens de tester ce que tu m'a dis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    export OMP_NUM_THREADS=1 && time ./application : 
    real    1m27.924s
    user    1m27.740s
    sys     0m0.017s
     
    export OMP_NUM_THREADS=2 && time ./application : 
    real    2m46.144s
    user    2m45.802s
    sys     0m0.025s
     
    export OMP_NUM_THREADS=4 && time ./application : 
    real    2m42.303s
    user    2m41.992s
    sys     0m0.007s
     
    export OMP_NUM_THREADS=8 && time ./application : 
    real    2m11.748s
    user    2m11.492s
    sys     0m0.009s
    C'est clairement plus long à l'appel de plusieurs treads ...

  8. #8
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Il va nous falloir plus de détails sur le vrai code.
    Sur le code jouet, tu obtiens des performances ?

  9. #9
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Novembre 2011
    Messages : 18
    Par défaut
    En fait, mon code est un algorithme MCMC(markov chain monte carlo) qui compare des données simulées à des données réelles pour inférer des paramètres d'un modèle.
    A chaque itération du MCMC et pour chaque paramètres de mon modèle, l'algorithme propose une valeur de paramètre, simule le jeu de donnée avec celui ci et le compare avec le jeu de donnée réel.
    Pour savoir si l’algorithme "accepte" la valeur proposée du paramètre, il doit calculer un ratio et donc simuler deux fois les sorties du modèle...

    C'est a ce moment la que je voudrais utiliser openMP, une réalisation du modèle met environ 40s, c'est pourquoi je voudrais pouvoir simuler les réalisations (qui sont indépendantes , seul les paramètres changent) sur deux cœurs en même temps.

    Mais du coup... je ne sais pas si c'est faisable ...

Discussions similaires

  1. Réponses: 5
    Dernier message: 06/06/2011, 01h04
  2. Mesure du temps de calcul avec time.clock()
    Par céline80 dans le forum Général Python
    Réponses: 2
    Dernier message: 21/09/2009, 17h02
  3. Réponses: 0
    Dernier message: 04/08/2008, 17h05
  4. Temps de calcul avec deux écrans
    Par Shaga dans le forum OpenGL
    Réponses: 2
    Dernier message: 14/11/2005, 09h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo