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 :

Fonction rand()


Sujet :

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

  1. #1
    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()
    Bonjour,

    ci dessous un code très bête qui consiste à appeler 10000000 fois la fonction rand() dans 1 thread (pas de seed, le code est stupide mais c'est pour illustrer...)

    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
    /* to compile: gcc -Wall -fopenmp -o dummy dummy.c */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <omp.h>
     
    int main()
    {
    	int numTH = 1;
    	int k,l;
     
    	/* Begin parallel region */
    	#pragma omp parallel private(k,l) num_threads(numTH)	
    	{
    		for(k=0;k<10000000;k++) l=rand();
     
    	}
     
    	return EXIT_SUCCESS;
    }
    je lance ce code depuis mon shell, avec la fonction time (qui permet de mesurer le temps d'exécution):
    time ./dummy

    real 0m0.099s
    user 0m0.096s
    sys 0m0.000s
    Faisons la même chose avec 2 threads (dans chaque thread on appelle 10000000 la fonction rand())

    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
    /* to compile: gcc -Wall -fopenmp -o dummy dummy.c */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <omp.h>
     
    int main()
    {
    	int numTH = 2;
    	int k,l;
     
    	/* Begin parallel region */
    	#pragma omp parallel private(k,l) num_threads(numTH)	
    	{
    		for(k=0;k<10000000;k++) l=rand();
     
    	}
     
    	return EXIT_SUCCESS;
    }
    je lance ce code depuis mon shell, avec la fonction time:
    time ./dummy

    real 0m4.753s
    user 0m4.080s
    sys 0m5.392s
    Comme indiqué dans l'en-tête de mes codes, dans les deux cas le code est compilé avec la commande:
    gcc -Wall -fopenmp -o dummy dummy.c
    Quelqu'un saurait expliquer cette explosion du temps de calcul?
    Et surtout comment résoudre ce problème??

    Merci d'avance pour vos réponses.
    RémyA

  2. #2
    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 rand() n'est pas thread-safe
    J'ai l'explication et un début de solution:

    La fonction rand() est dite "non-thread-safe", elle définie visiblement une région "atomic" qui protège ses variables "static" des accès simultanés. Ainsi utiliser rand() dans une région parallèle ralenti considérablement le programme.

    Une solution (mais elle n'est pas très efficace d'après mes tests) est d'utiliser rand_r() à la place de rand(). rand_r est "thread-safe" elle peut donc être utilisée dans des régions parallèles. Elle prend en argument un pointeur vers une variable d'initialisation. Pour l'utiliser correctement chaque thread doit avoir sa propre variable d'initialisation, et à chaque exécution du programme les variables d'initialisations doivent être différentes (sans quoi on génère toujours les mêmes nombres).

    Ainsi je propose le code suivant:

    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
    /* to compile: gcc -fopenmp -o dummy2 dummy2.c */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <omp.h>
     
    int main()
    {
    	int numTH = 2;
     
    	int k,l,m;
    	unsigned int *seed;
     
    	/* rand() seed */
    	srand((long int) time(NULL));
     
    	/* r_rand seed table */
    	seed = (unsigned int*)malloc(numTH*sizeof(unsigned int));
    	for(k=0;k<numTH;k++) seed[k] = rand();
     
    	/* Begin parallel region */
    	#pragma omp parallel for private(k,l,m) shared(seed,numTH) num_threads(numTH)	
    	for(k=0;k<numTH;k++)
    	{
    		for(l=0;l<10000000;l++) m =rand_r(&seed[k]); 
    	}
     
    	/* free memory */
    	free(seed);
     
    	return EXIT_SUCCESS;
    }
    Ce code est bien plus satisfaisant en termes de temps d'exécution, voici quelques mesures sur un serveur à 48 processeurs (tous les processeurs étaient disponibles à 100% pendant mes tests):
    1 thread >> ~ 140ms
    2 threads >> ~ 440ms
    5 threads >> ~ 1s
    10 threads >> ~ 1.4s
    15 threads >> ~ 2.8s
    20 threads >> ~ 4s
    Bref, c'est moins catastrophique en termes de temps d'exécution, mais ce n'est toujours pas satisfaisant , ça ne devrait pas augmenter comme cela. Certes il faut un peu de temps pour la gestion du fork & join, mais pas autant, ça se vérifie facilement sur des codes simples. De plus le temps perdu à gérer les threads est sensé être kiff-kiff pour 2 threads ou N threads tant que N est inférieur ou égal au nombre de processeurs disponibles.

    Quelqu'un a une idée?

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    C'est normal vous ne parallelisez pas la boucle en L donc sur 1 procs on a 10M d'appels et sur 2 procs on a 20M d'appels donc au moins deux fois plus de temps.

    Ensuite difficile de diviser par x un code qui met 140ms sur 1 procs.

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Compile avec l'option -O3 (pour activer la plupart des optimisations), tu ne devrais plus avoir de telles différences (mais pas de gain non plus).

Discussions similaires

  1. la fonction rand()
    Par bonomsoleil dans le forum C
    Réponses: 10
    Dernier message: 16/11/2006, 22h43
  2. [Mail] valider par mail un formulaire et fonction rand
    Par guillaume2vo dans le forum Langage
    Réponses: 2
    Dernier message: 17/09/2006, 20h37
  3. fonction rand() sur liste ?
    Par debutant-1 dans le forum C
    Réponses: 10
    Dernier message: 24/05/2006, 10h58
  4. Algo de la fonction RAND
    Par booby dans le forum C
    Réponses: 3
    Dernier message: 21/04/2006, 14h25
  5. fonction rand() php
    Par taka10 dans le forum Langage
    Réponses: 5
    Dernier message: 12/04/2006, 13h35

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