2010-12-22 3 views
3

J'essaie de comprendre un code openmp de here. Vous pouvez voir le code ci-dessous.Faible performance dans un programme OpenMP

  1. Afin de mesurer l'accélération, la différence entre la version de série et OMP, j'utilise time.h, trouvez-vous juste cette approche?

  2. Le programme s'exécute sur une machine à 4 coeurs. Je spécifie export OMP_NUM_THREADS="4" mais ne peux pas voir sensiblement accélérer, habituellement je reçois 1.2 - 1.7. A quels problèmes suis-je confronté dans cette parallélisation?

  3. Quel outil de débogage/performance pourrais-je utiliser pour voir la perte de performance?

code (pour la compilation J'utilise xlc_r -qsmp=omp omp_workshare1.c -o omp_workshare1.exe)

#include <omp.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
#define CHUNKSIZE 1000000 
#define N  100000000 

int main (int argc, char *argv[]) 
{ 
    int nthreads, tid, i, chunk; 
    float a[N], b[N], c[N]; 
    unsigned long elapsed; 
    unsigned long elapsed_serial; 
    unsigned long elapsed_omp; 
    struct timeval start; 
    struct timeval stop; 


    chunk = CHUNKSIZE; 

    // ================= SERIAL  start ======================= 
    /* Some initializations */ 
    for (i=0; i < N; i++) 
     a[i] = b[i] = i * 1.0; 
    gettimeofday(&start,NULL); 
    for (i=0; i<N; i++) 
    { 
     c[i] = a[i] + b[i]; 
     //printf("Thread %d: c[%d]= %f\n",tid,i,c[i]); 
    } 
    gettimeofday(&stop,NULL); 
    elapsed = 1000000 * (stop.tv_sec - start.tv_sec); 
    elapsed += stop.tv_usec - start.tv_usec; 
    elapsed_serial = elapsed ; 
    printf (" \n Time SEQ= %lu microsecs\n", elapsed_serial); 
    // ================= SERIAL  end ======================= 


    // ================= OMP start ======================= 
    /* Some initializations */ 
    for (i=0; i < N; i++) 
     a[i] = b[i] = i * 1.0; 
    gettimeofday(&start,NULL); 
#pragma omp parallel shared(a,b,c,nthreads,chunk) private(i,tid) 
    { 
     tid = omp_get_thread_num(); 
     if (tid == 0) 
     { 
      nthreads = omp_get_num_threads(); 
      printf("Number of threads = %d\n", nthreads); 
     } 
     //printf("Thread %d starting...\n",tid); 

#pragma omp for schedule(static,chunk) 
     for (i=0; i<N; i++) 
     { 
      c[i] = a[i] + b[i]; 
      //printf("Thread %d: c[%d]= %f\n",tid,i,c[i]); 
     } 

    } /* end of parallel section */ 
    gettimeofday(&stop,NULL); 
    elapsed = 1000000 * (stop.tv_sec - start.tv_sec); 
    elapsed += stop.tv_usec - start.tv_usec; 
    elapsed_omp = elapsed ; 
    printf (" \n Time OMP= %lu microsecs\n", elapsed_omp); 
    // ================= OMP end ======================= 
    printf (" \n speedup= %f \n\n", ((float) elapsed_serial)/((float) elapsed_omp)) ; 

} 
+0

Vous pouvez également spécifier quel système d'exploitation et quel compilateur pour aider les autres à répondre aux questions n ° 1 et n ° 3. –

Répondre

1

Il n'y a rien vraiment mal avec le code comme ci-dessus, mais votre speedup va être limité par le fait que la boucle principale, c = a + b, a très peu de travail - le temps nécessaire pour faire le calcul (une seule addition) va être dominé par le temps d'accès à la mémoire (2 charges et un magasin), et il y a plus de conflits de bande passante sur le tableau.

Nous pouvons tester cela en faisant le travail à l'intérieur de la boucle plus calcul intensif:

c[i] = exp(sin(a[i])) + exp(cos(b[i])); 

Et nous obtenons

$ ./apb 

Time SEQ= 17678571 microsecs 
Number of threads = 4 

Time OMP= 4703485 microsecs 

speedup= 3.758611 

qui est évidemment beaucoup plus proche de la 4x speedup un serait attendre.

Mise à jour: Oh, et aux autres questions - gettimeofday() est probablement bien pour le timing, et sur un système où vous utilisez xlc - est-ce AIX? Dans ce cas, peekperf est un bon outil de performance globale, et les moniteurs de performance du matériel vous donneront accès aux temps d'accès à la mémoire. Sur les plates-formes x86, les outils gratuits pour la surveillance des performances du code thread incluent cachegrind/valgrind pour le débogage des performances du cache (pas le problème ici), scalasca pour les problèmes OpenMP généraux et OpenSpeedShop est également très utile.

Questions connexes