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

Programmation parallèle, calcul scientifique et de haute performance (HPC) Discussion :

Parallélisme plus lent [OpenMP]


Sujet :

Programmation parallèle, calcul scientifique et de haute performance (HPC)

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 13
    Points : 10
    Points
    10
    Par défaut Parallélisme plus lent
    Voila donc suite à mon autre sujet sur GCC, j'ai un problème de parallélisme sur ma machine (OS X Lion).
    En effet ce qui m'avait amené à me demander si je devais pas passer de gcc 4.2 à gcc 4.7, c'est le fait qu'à chaque fois que j'exécuter un code avec openMP pour qu'il soit lancé en parallèle, celui ci avec une exécution beaucoup plus lente que lors de son exécution en séquentiel.
    Voici mon code :

    Code c : 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
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    #include <omp.h>
     
    void carre (int tab[], int *n);
     
    int main (int argc, const char * argv[])
    {
    	int size, i;
    	int* tab = NULL;
    	const int MAX = 30000;
    	const int MIN = 100;
    	srand(time(NULL));
     
    	printf("Choisissez la taille de votre tableau ");
    	scanf("%d", &size);
     
    	tab = malloc(size * sizeof(int));
    	if (tab == NULL) {
    		exit(0);
    	}
     
    	printf("\n\nVotre tableau est le suivant :\n");
        #pragma omp parallel for
    	for (i = 0 ; i < size ; i++)
    	{
    		tab[i] = (rand() % (MAX - MIN + 1)) + MIN;
    		printf("t[%d] = %d \n", i, tab[i]);
    	}
    	printf("\n\n");
    	carre(tab, &size);
     
    	free(tab);
    	return 0;
    }
     
    void carre (int* tab, int*n){
    	int j;
        #pragma omp parallel for
    	for (j = 0 ; j < *n ; j++){
    		tab[j] = tab[j] * tab[j];
    		printf("carre [%d] : %d\n", j, tab[j]);
    	}
    }

    Puis dans le terminal, lorsque je veux exécuter ce code en parallèle, je tape "gcc main.c -fopenmp" puis "time ./a.out" avec une taille de tableau de 10 000 000 pour vraiment voir si le parallélisme est plus rapide. Or c'est tout le contraire il mettra beaucoup plus de temps que lorsque je lance en séquentiel avec simplement "gcc main.c" et "time ./a.out". Pour un tableau de cette taille je vais même 2 fois plus vite en sequentiel qu'en parallèle.

    D'où pourrais venir ce problème?

    Ce qui m'embête c'est que par la suite je vais devoir travailler en // très souvent, et si déja lors des premiers TP ma machine ne tourne pas en // c'est assez contraignant.

  2. #2
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Je confirme la même chose sous linux et gcc4.7 (en ayant viré les prints dans les boucles, ça ralentit horriblement les choses*!)*:

    Avec openmp*:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real	0m9.686s
    user	0m4.228s
    sys	0m25.554s
    Sans*:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real	0m7.566s
    user	0m0.588s
    sys	0m0.048s
    Non seulement le temps “réel” est un peu plus long, mais surtout le temps réellement utilisé par le programme (user) et les appels systèmes (sytem) est lui carrément catastrophique*!

    Je pense qu’on a là un bon exemple de cas où il vaut mieux éviter la parallélisation*: les traitements a effectuer dans chaque boucle sont tellement basiques et rapides a effectuer que la parallélisation coûte beaucoup plus cher qu’elle ne rapporte*!

    Pour preuve, avec ce code*:

    Code c : 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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    #include <omp.h>
     
    void carre (int tab[], int *n);
     
    int main (int argc, const char * argv[])
    {
    	int size, i;
    	int* tab = NULL;
    	const int MAX = 30000;
    	const int MIN = 100;
    	srand(time(NULL));
     
    	printf("Choisissez la taille de votre tableau ");
    	scanf("%d", &size);
     
    	tab = malloc(size * sizeof(int));
    	if (tab == NULL) {
    		exit(0);
    	}
     
    	printf("\n\nVotre tableau est le suivant :\n");
    /*    #pragma omp parallel for*/
    	for (i = 0 ; i < size ; i++)
    	{
    		tab[i] = (rand() % (MAX - MIN + 1)) + MIN;
    /*		printf("t[%d] = %d \n", i, tab[i]);*/
    	}
    	printf("\n\n");
    	carre(tab, &size);
     
    	free(tab);
    	return 0;
    }
     
    void carre (int* tab, int*n){
    	int j;
        #pragma omp parallel for
    	for (j = 0 ; j < *n ; j++){
    		int k;
    		for (k = 10000; k; k--) {
    			tab[j] = tab[j] * tab[j] + k;
    		}
    /*		printf("carre [%d] : %d\n", j, tab[j]);*/
    	}
    }

    … voici ce que ça donne (pour une taille de tableau de 100000, cette fois)*:

    Avec OpenMP*:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real	0m7.927s
    user	0m31.714s
    sys	0m0.020s
    Et sans*:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    real	0m16.441s
    user	0m13.157s
    sys	0m0.008s
    CQFD…

    [edit]J’ai oublié de préciser que ces valeurs sont obtenues avec un octo-cœurs… On remarque que le temps effectivement passé en user space reste deux fois supérieur avec OpenMP que sans*![/edit]

    Sans oublier que openmp n’est pas aussi efficace (et de loin) que l’utilisation directe des threads, son principal avantage est sa facilité de mise en œuvre…

  3. #3
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Tu as déjà un souci de masse : l'accès concurrentiel à une ressource critique.
    A savoir la sortie standard.
    Si tu enlèves le printf dans ta boucle tu gagneras déjà énormément en parallélisation. Surtout sachant que dans un programme la fonction qui prend le plus de temps est l'affichage.

    Après il ne faut pas prendre la formule d'Amdalh au premier degré. Car tout traitement n'est pas rentable à être parallélisé comme le disait aussi mont29, il y a en effet la somme des temps de changement de contexte pour ton traitement global qui rentre en ligne de compte.

    Je ne pourrais pas te donner d'améliorations sur OpenMP ne l'ayant jamais utilisé, je reste dans mes travaux à la parallélisation via des threads à la mano. Car comme l'indique encore très justement le message ci-dessus toutes les librairies seront forcement un poil plus lentes que le natif. On n'y gagne qu'en temps de développement.

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

  4. #4
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par flo2708 Voir le message
    Voila donc suite à mon autre sujet sur GCC, j'ai un problème de parallélisme sur ma machine (OS X Lion).
    En effet ce qui m'avait amené à me demander si je devais pas passer de gcc 4.2 à gcc 4.7, c'est le fait qu'à chaque fois que j'exécuter un code avec openMP pour qu'il soit lancé en parallèle, celui ci avec une exécution beaucoup plus lente que lors de son exécution en séquentiel.
    [...]
    D'où pourrais venir ce problème?

    Ce qui m'embête c'est que par la suite je vais devoir travailler en // très souvent, et si déja lors des premiers TP ma machine ne tourne pas en // c'est assez contraignant.
    Bonjour,
    Ta «machine tourne bien en parallèle», le programme donne bien le bon résultat.

    OMP fait beaucoup de chose que tu ne vois/codes pas en l'utilisant comme tu l'utilises : création de pool de threads, distribution du travail, attente lors de barrières, finalisation, etc ... tout cela prend du temps (non négligeable).
    OMP n'est pas non plus un outil magique (=on rajoute des #pragma et tout tourne deux fois plus vite). Il y a énormément de doc à ce sujet : quelle structure utiliser dans quel cas, comment l'intégrer efficacement dans un programme séquentiel et à quel endroit.

    OMP n'est qu'une spec pour proposer un paradigme de programmation parallèle. De nombreux compilateurs l'implément sur de nombreuses plateformes : ça permet une grande portabilité (peu importe que ta plateforme/compilateur utilise les pthread ou les threads windows ou que tu développes sur un quadri processeurs 32 coeurs et que ton appli tourne sur un portable, il s'adapte). Il permet aussi de peu modifier un code séquentiel existant : c'est plus simple d'ajouter quelques pragmas, quelques appels de fonctions omp* et adapter un minimum le code, plutôt que d'y ajouter une gestion manuelle des threads.
    Il peut arriver que le code séquentiel ne puisse pas tirer profit d'openmp :

    * l'algorithme est essentiellement séquentiel, la parallélisation n'apporte rien en terme de performance.

    * l'algorithme est esssentiellement séquentiel, il existe bien un algorithme parallèle mais l'implémenter nécessite une grosse refonte de ton code

    * le programme est suffisament rapide que le paralléliser ajoute un temps de traitement tel que la version séquentielle est plus rapide

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2012
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 13
    Points : 10
    Points
    10
    Par défaut
    Parfait merci pour vos reponses, j'arrive bien a aller plus vite en // maintenant.
    C'est vrai que les printf bouffent pas mal de temps, pour pas dire la totalité du temps

  6. #6
    Nouveau membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mai 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2007
    Messages : 47
    Points : 36
    Points
    36
    Par défaut fonction rand() & openMP
    Bonjour,

    Je sais que le sujet a été marqué comme résolu, mais il me semble qu'un point important n'a pas été abordé. Vous utilisez la fonction rand() dans une région parallèle , or cette fonction n'est pas "thread-safe" (cf forum officiel OpenMP pour voir des discussions sur le sujet). Elle définie une région critique qui protège ses variables statiques des accès simultanés, c'est selon moi ce qui ralenti votre code.

    La fonction rand_r semble plus adapté mais pas idéale pour autant... Je vous invite à consulter mon dernier post qui illustre à l'aide d'un code simple le problème de la génération de variables pseudo-aléatoires avec openMP.

    J'insiste sur le fait que le code est stupide, il ne fait rien, mais il ne fait que 20 lignes et isole bien le problème.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 76
    Dernier message: 29/03/2011, 16h15
  2. Pourquoi surfer sous linux est plus lent sous suse
    Par spiwis dans le forum Applications et environnements graphiques
    Réponses: 5
    Dernier message: 12/12/2005, 12h21
  3. [Système] Mozilla plus lent que IE
    Par Halleck dans le forum Langage
    Réponses: 6
    Dernier message: 22/06/2005, 17h26
  4. [Firebird][Optimisation]Plus lent que le BDE!
    Par vincentj dans le forum Débuter
    Réponses: 3
    Dernier message: 07/02/2005, 15h48
  5. DBExpress est plus lent que BDE?
    Par palassou dans le forum Bases de données
    Réponses: 4
    Dernier message: 02/07/2004, 08h39

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