- Premier exemple
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc,char *argv[])
{
/********************* debut region parallele *********************/
#pragma omp parallel
{
printf("[%s:%d] : thread %d/%d, nbproc = %d\n",__FILE__,__LINE__,
omp_get_thread_num()+1,omp_get_num_threads(),omp_get_num_procs());
}
/********************* fin region parallele *********************/
return EXIT_SUCCESS;
}
- résultats à l'exécution :
% cc -version
MIPSpro Compilers: Version 7.3.1.1m
% cc -mp exemple1.c
% export OMP_NUM_THREADS=5
% ./a.out
[exemple1.c:10] : thread 2/5, nbproc = 64
[exemple1.c:10] : thread 5/5, nbproc = 64
[exemple1.c:10] : thread 4/5, nbproc = 64
[exemple1.c:10] : thread 3/5, nbproc = 64
[exemple1.c:10] : thread 1/5, nbproc = 64
%
- Deuxième exemple - opération de réduction
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc,char *argv[])
{
int quiSuisJe,somme=0,nbproc;
/********************* debut region parallele *********************/
#pragma omp parallel shared(nbproc) private(quiSuisJe) reduction(+:somme)
{
nbproc = omp_get_num_threads();
quiSuisJe = omp_get_thread_num()+1;
somme += quiSuisJe;
printf("[thread %d/%d] : somme intermediaire = %d\n",
quiSuisJe,nbproc,somme);
}
/********************* fin region parallele *********************/
printf("somme totale apres reduction = %d (theorique = %d)\n",
somme,(nbproc*(nbproc+1))/2);
return EXIT_SUCCESS;
}
- résultats à l'exécution :
% cc -mp exemple2.c
% export OMP_NUM_THREADS=7
% ./a.out
[thread 2/7] : somme intermediaire = 2
[thread 3/7] : somme intermediaire = 3
[thread 6/7] : somme intermediaire = 6
[thread 5/7] : somme intermediaire = 5
[thread 4/7] : somme intermediaire = 4
[thread 7/7] : somme intermediaire = 7
[thread 1/7] : somme intermediaire = 1
somme totale apres reduction = 28 (theorique = 28)
%
- Troisième exemple - boucle for
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc,char *argv[])
{
int i,N=10,tableau[N];
for (i=0 ; i<N ; i++)
tableau[i]=1;
/********************* debut region parallele *********************/
#pragma omp parallel for shared(tableau) private(i,N)
for (i=0 ; i<N ; i++)
tableau[i] += omp_get_thread_num();
/********************* fin region parallele *********************/
for (i=0 ; i<N ; i++)
printf("[%d]=%d ",i,tableau[i]);
printf("\n");
return EXIT_SUCCESS;
}
- résultats à l'exécution :
% cc -mp exemple3.c
% export OMP_NUM_THREADS=3
% ./a.out
[0]=1 [1]=1 [2]=1 [3]=1 [4]=2 [5]=2 [6]=2 [7]=3 [8]=3 [9]=3
%
- Quatrième exemple - boucle for et opération de réduction
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc,char *argv[])
{
int i , somme = 0 , N = atoi(argv[1]);
/********************* debut region parallele *********************/
#pragma omp parallel for firstprivate(N) private(i) reduction(+:somme)
for(i=1 ; i<=N ; i++)
{
somme += i;
printf("[thread %d/%d] : somme intermediaire = %d\n",
omp_get_thread_num()+1,omp_get_num_threads(),somme);
}
/********************* fin region parallele *********************/
printf("somme des entiers de 1 a %d apres reduction = %d (theorique = %d)\n",
N,somme,(N*(N+1))/2);
return EXIT_SUCCESS;
}
- résultats à l'exécution :
% cc -mp exemple4.c
% export OMP_SCHEDULE=STATIC
% export OMP_NUM_THREADS=4
% ./a.out 10
[thread 1/4] : somme intermediaire = 1
[thread 4/4] : somme intermediaire = 9
[thread 3/4] : somme intermediaire = 7
[thread 2/4] : somme intermediaire = 4
[thread 1/4] : somme intermediaire = 3
[thread 4/4] : somme intermediaire = 19
[thread 3/4] : somme intermediaire = 15
[thread 2/4] : somme intermediaire = 9
[thread 1/4] : somme intermediaire = 6
[thread 2/4] : somme intermediaire = 15
somme des entiers de 1 a 10 apres reduction = 55 (theorique = 55)
%
- Cinquième exemple - application au calcul d'une valeur approchée de PI
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
#define f(a) (4.0 / (1.0 + (a)*(a)))
#ifdef _OPENMP
/*
* si l'on compile avec l'option -mp, cette region est activee car le "drapeau
* _OPENMP" est positionne. Si l'option -mp n'est pas specifiee a la
* compilation, on "fait" du sequentiel pur !
*/
#define TYPECOMPILATION "parallele"
#else
#define TYPECOMPILATION "sequentiel"
#endif
int question()
{
int n=0;
printf("Entrez le nombre d'intervalles (et 0 pour terminer) : ");
scanf("%d",&n);
return n;
}
int main(int argc,char *argv[])
{
typedef enum{false=0,true=1} boolean;
double somme,pas,pi,piRef = 3.141592653589793;
int n,i;
boolean continuer = true;
while (continuer) {
if ((n = question()) == 0)
continuer = false;
else {
pas = 1.0/(double)n;
somme = 0.0;
/********************* debut region potentiellement parallele *********************/
#ifdef _OPENMP
/*
* si l'on compile avec l'option -mp, cette region est activee car le "drapeau
* _OPENMP" est positionne. Si l'option -mp n'est pas specifiee a la
* compilation, on "fait" du sequentiel pur !
*/
#pragma omp parallel for firstprivate(n) private(i) reduction(+:somme)
#endif
for (i=1; i<=n; i++)
somme += f(pas * ((double)i - 0.5));
/********************* fin region potentiellement parallele *********************/
pi = pas * somme;
printf("Valeur approchee de PI : %.15f, Erreur : %.15f\n",
pi, fabs(pi - piRef));
printf("Calcul %s sur %d intervalles.\n",TYPECOMPILATION,n);
}
}
return EXIT_SUCCESS;
}
- résultats à l'exécution :
% export OMP_SCHEDULE=STATIC
% export OMP_NUM_THREADS=4
% cc exemple5.c && ./a.out
Entrez le nombre d'intervalles (et 0 pour terminer) : 10000
Valeur approchee de PI : 3.141592654423134, Erreur : 0.000000000833341
Calcul sequentiel sur 10000 intervalles.
Entrez le nombre d'intervalles (et 0 pour terminer) : 0
% cc -mp exemple5.c && ./a.out
Entrez le nombre d'intervalles (et 0 pour terminer) : 10000
Valeur approchee de PI : 3.141592654423124, Erreur : 0.000000000833331
Calcul parallele sur 10000 intervalles.
Entrez le nombre d'intervalles (et 0 pour terminer) : 0
%
- Sixième exemple - couplage OpenMP et MPI
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <omp.h>
int main(int argc,char *argv[])
{
int rang,nbpcs;
double debut,fin; /* chronometrage */
char nomProcesseur[MPI_MAX_PROCESSOR_NAME];
int longNomProcesseur;
debut = MPI_Wtime();
if (MPI_Init(&argc,&argv) != MPI_SUCCESS)
exit(EXIT_FAILURE);
MPI_Get_processor_name(nomProcesseur,&longNomProcesseur);
MPI_Comm_rank(MPI_COMM_WORLD,&rang);
MPI_Comm_size(MPI_COMM_WORLD,&nbpcs);
/********************* debut region OpenMP *********************/
#pragma parallel numthreads(3)
{
printf("processus MPI %d/%d sur %s -- tache OpenMP %d/%d\n",
rang,nbpcs,nomProcesseur,
omp_get_thread_num(),omp_get_num_threads());
}
/********************* fin region OpenMP *********************/
MPI_Finalize();
fin = MPI_Wtime();
printf("processus MPI %d/%d meurt apres %g secondes\n",
rang,nbpcs,fin-debut);
return EXIT_SUCCESS;
}
- résultats à l'exécution :
% cc exemple6.c -mp -lmpi
% mpirun -np 2 ./a.out
processus MPI 1/2 sur bacchus -- tache OpenMP 1/3
processus MPI 1/2 sur bacchus -- tache OpenMP 0/3
processus MPI 0/2 sur bacchus -- tache OpenMP 1/3
processus MPI 0/2 sur bacchus -- tache OpenMP 2/3
processus MPI 0/2 sur bacchus -- tache OpenMP 0/3
processus MPI 1/2 sur bacchus -- tache OpenMP 2/3
processus MPI 0/2 meurt apres 1.15706 secondes
processus MPI 1/2 meurt apres 1.16433 secondes
%