2010-02-07 6 views
6

Sono abbastanza nuovo su OpenMP e sto provando ad avviare un singolo thread per elaborare ogni elemento in un array 2D.Avvio di una discussione per ciascun ciclo interno in OpenMP

Quindi, in sostanza, questo:

for (i = 0; i < dimension; i++) { 
    for (int j = 0; j < dimension; j++) { 
     a[i][j] = b[i][j] + c[i][j]; 

Quello che sto facendo è questo:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic) 
    for (i = 0; i < dimension; i++) { 
     for (int j = 0; j < dimension; j++) { 
      a[i][j] = b[i][j] + c[i][j]; 

Questo infatti avviare un thread per ogni elemento 2D o no? Come potrei testarlo? Se è sbagliato, qual è il modo corretto per farlo? Grazie!

Nota: Il codice è stato notevolmente semplificato

+0

potrebbe desiderare di contrassegnare con la lingua che si sta utilizzando, anche se dovresti rimuovere uno dei tag esistenti. –

+0

mmyers buon punto - per riferimento sembra che stia usando c/C++ (openMP è c/C++ e fortran solo) –

risposta

7

solo l'anello esterno è parallela nel codice di esempio. È possibile eseguire il test stampando omp_get_thread_num() nel ciclo interno e vedrete che, per un dato i, il numero di thread è lo stesso (ovviamente, questo test è dimostrativo piuttosto che definitivo dato che esecuzioni diverse daranno risultati diversi). Ad esempio, con:

#include <stdio.h> 
#include <omp.h> 
#define dimension 4 

int main() { 
    #pragma omp parallel for 
    for (int i = 0; i < dimension; i++) 
     for (int j = 0; j < dimension; j++) 
      printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num()); 
    } 

ottengo:

i=1, j=0, thread = 1 
i=3, j=0, thread = 3 
i=2, j=0, thread = 2 
i=0, j=0, thread = 0 
i=1, j=1, thread = 1 
i=3, j=1, thread = 3 
i=2, j=1, thread = 2 
i=0, j=1, thread = 0 
i=1, j=2, thread = 1 
i=3, j=2, thread = 3 
i=2, j=2, thread = 2 
i=0, j=2, thread = 0 
i=1, j=3, thread = 1 
i=3, j=3, thread = 3 
i=2, j=3, thread = 2 
i=0, j=3, thread = 0 

Per quanto riguarda il resto del codice, si potrebbe desiderare di mettere più dettagli in una nuova domanda (è difficile dire dal piccolo campione), ma ad esempio, non è possibile inserire private(j) quando j viene dichiarato solo in seguito. È automaticamente privato nel mio esempio sopra. Immagino che diff sia una variabile che non possiamo vedere nell'esempio. Inoltre, la variabile del ciclo i è automaticamente privata (dal version 2.5 spec - stesso nella specifica 3,0)

L'iterazione del ciclo variabile nel per-loop di un pro o parallela per costrutto è privato in questo costrutto .

Modifica: tutto quanto sopra è corretto per il codice che tu ed io abbiamo mostrato, ma potresti essere interessato a quanto segue. Per OpenMP versione 3.0 (disponibile ad esempio gcc version 4.4, ma non versione 4.3) esiste una clausola collapse in cui è possibile scrivere il codice come si dispone, ma con #pragma omp parallel for collapse (2) in parallelo per entrambi i loop (vedere the spec).

Edit: OK, ho scaricato gcc 4.5.0 e ha eseguito il codice di cui sopra, ma utilizzando collapse (2) per ottenere il risultato seguente, che mostra il ciclo interno ora parallelizzato:

i=0, j=0, thread = 0 
i=0, j=2, thread = 1 
i=1, j=0, thread = 2 
i=2, j=0, thread = 4 
i=0, j=1, thread = 0 
i=1, j=2, thread = 3 
i=3, j=0, thread = 6 
i=2, j=2, thread = 5 
i=3, j=2, thread = 7 
i=0, j=3, thread = 1 
i=1, j=1, thread = 2 
i=2, j=1, thread = 4 
i=1, j=3, thread = 3 
i=3, j=1, thread = 6 
i=2, j=3, thread = 5 
i=3, j=3, thread = 7 

Commenti here (ricerca di "Soluzioni alternative") sono rilevanti anche per il work-around nella versione 2.5 se si desidera parallelizzare entrambi i cicli, ma la specifica della versione 2.5 citata sopra è piuttosto esplicita (vedere gli esempi non conformi nella sezione A.35).

+0

Grazie, il crollo era il trucco che stavo cercando! – achinda99

0

È possibile provare a utilizzare i paralleli omp annidati (dopo la chiamata omp_set_nested(1)), ma non sono supportati su tutte le implementazioni di openmp.

Quindi credo che per fare un po 'di griglia 2D e ricominciare tutto thread su griglia da sola per (ad esempio per la griglia di filo 4x4 fisso):

#pragma omp parallel for 
for(k = 0; k < 16; k++) 
{ 
    int i,j,i_min,j_min,i_max,j_max; 
    i_min=(k/4) * (dimension/4); 
    i_max=(k/4 + 1) * (dimension/4); 
    j_min=(k%4) * (dimension/4); 
    j_max=(k%4 + 1) * (dimension/4); 

    for(i=i_min;i<i_max;i++) 
     for(j=j_min;j<j_max;j++) 
     f(i,j); 

}