Domanda

Sono abbastanza nuovo per OpenMP e sto cercando di avviare un singolo thread per elaborare ogni elemento in un array 2D.

Quindi, in sostanza, in questo modo:

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 ho iniziato ad esaminare questo? Se è sbagliato, qual è il modo corretto per farlo? Grazie!

Nota: Il codice è stato notevolmente semplificato

È stato utile?

Soluzione

Solo l'anello esterno è parallela nel codice di esempio. È possibile verificare stampando omp_get_thread_num() nel ciclo interno e vedrete che, per un dato i, il num thread è lo stesso (ovviamente, questo test è dimostrativo piuttosto che definitivo, in quanto diverse corse darà 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 per esempio, non si può mettere private(j) quando j viene dichiarato solo più tardi. E 'automaticamente privato nel mio esempio di cui sopra. Credo che diff è una variabile che non possiamo vedere nel campione. Inoltre, il ciclo i variabile è automaticamente privata (dal 2.5 spec - stesso nelle specifiche 3.0)

  

La variabile iterazione del ciclo nel   for-loop di un pro o parallelo   costrutto è privata in quel   costruire.

Modifica: Tutto quanto sopra è corretto per il codice che tu ed io abbiamo dimostrato, ma si potrebbe essere interessato al seguito. Per OpenMP versione 3.0 (disponibile in esempio gcc versione 4.4 , ma non la versione 4.3) c'è una clausola collapse dove si poteva scrivere il codice come si deve, ma con #pragma omp parallel for collapse (2) per parallelizzare sia per i loop (vedi le specifiche ).

Modifica : 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

href="http://bisqwit.iki.fi/story/howto/openmp/#LoopDirectiveFor" qui (ricerca di "Soluzioni alternative") sono rilevanti anche per work-around in versione 2.5, se si vuole parallelizzare entrambi i loop, ma la versione 2.5 spec citata è molto esplicito (vedi gli esempi non conformi nella sezione A.35 ).

Altri suggerimenti

Si può provare di usare nidificato OMP fors paralleli (dopo la chiamata omp_set_nested(1)), ma un non supportato su tutte le implementazioni OpenMP.

Quindi immagino fare qualche griglia 2D e ricominciare tutto filetto su griglia da sola per (esempio per griglia 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);

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top