2016-03-31 26 views
5

Sto provando a utilizzare i task openmp per pianificare un'esecuzione affiancata del calcolo di base di jacobi2d. In jacobi2d c'è una dipendenza A (i, j) daLa clausola di dipendenza in openmp non sta rispettando la dipendenza dichiarata

A (i, j)
A (i-1, j)
A (i + 1, j)
A (i, j-1)
A (i, j + 1).

Per la mia comprensione della clausola dipende sto dichiarando le dipendenze in modo corretto, ma non sono rispettati durante l'esecuzione del codice. Ho copiato il pezzo di codice semplificato qui sotto. Inizialmente la mia ipotesi era che gli intervalli fuori limite per alcune tessere potessero causare questo problema, quindi l'ho corretto, ma il problema persiste. (Non ho copiato il codice più lungo con intervalli di tile corretti dato che quella parte è solo un mucchio di if + max)

int n=8,tsteps=2,b=4;   //n - size of matrix, tsteps - time iterations, b - tile size or block size 

#pragma omp parallel 
{ 
#pragma omp master 
for (t=0; t<tsteps; ++t) 
    { 
    for (i=0; i<n; i+=b) 
     for (j=0; j<n; j+=b) 
     { 
     #pragma omp task firstprivate(t,i,j) depend(in:A[i-1:b+2][j-1:b+2]) depend(out:B[i:b][j:b]) 
     { 
      #pragma omp critical 
      printf("t-%d i-%d j-%d --A",t,i,j);  //Prints out time loop, i,j 
     } 
     } 
    for (i=0; i<n; i+=b) 
     for (j=0; j<n; j+=b) 
     { 
     #pragma omp task firstprivate(t,i,j) depend(in:B[i-1:b+2][j-1:b+2]) depend(out:A[i:b][j:b]) 
     { 
      #pragma omp critical 
      printf("t-%d i-%d j-%d --B",t,i,j);  //Prints out time loop, i,j 
     } 
     } 
    } 
} 
} 

Così l'idea di dichiarare la dipendenza a partire da i-1 e j-1 e l'essere gamma (B + 2) è che le piastrelle vicini influenzano anche i vostri attuali calcoli piastrelle. E allo stesso modo per il secondo set di loop in cui i valori in A dovrebbero essere sovrascritti solo quando le tessere vicine hanno usato i valori.

Il codice viene compilato utilizzando gcc 5.3 che supporta openmp 4.0.

ps: l'intervallo di matrice modo viene dichiarato sopra indica la posizione di partenza e il numero di indici essere considerati durante la creazione del grafico dipendenza.

modifica (in base a commento di Zulan) - ha cambiato il codice interno di una semplice dichiarazione di stampa come questo sarà sufficiente per verificare ordine di esecuzione dell'attività. Idealmente per i valori di cui sopra (dato che ci sono solo 4 tessere) tutte le tessere dovrebbero completare la prima stampa e quindi eseguire solo la seconda. Ma se si esegue il codice, si mescolerà l'ordine.

+0

Perché non usi semplicemente la condivisione del lavoro sui loop? Nel primo ciclo leggiamo da 'B' ma scriviamo in' A'. Nel secondo ciclo scrivi a 'A' e leggi da' B'. Quindi fai prima la parte 1 in parallelo e poi la parte2 in parallelo. Assicurati di sincronizzare i thread tra part1 e part2 (che dovrebbe essere comunque implicito a meno che tu non usi 'nowait'). –

+1

Sicuramente le condizioni sono tutte sbagliate? ("if ((ii! = 0 || ii! = n-1) || (jj! = 0 || jj! = n-1))". Considera ii == 0, che verrà comunque eseguito da 0! = n-1, ma non lo si vuole perché genera un accesso fuori limite ... –

+0

@Zboson - Sì, si può fare anche questo, è solo che l'utilizzo di attività ti dà un uso leggermente più efficiente come idealmente più piccole mansioni ti danno è richiesto un parallelismo più alto e meno la sincronizzazione. @ Jim. Sì hai ragione, cioè un errore con il codice. il fatto è che il problema della dipendenza esiste ancora. ho rintracciato l'ordine di dipendenza e di esecuzione utilizzando un stampa singola prima dei 2 interni ii e jj per i cicli e l'ordine delle istruzioni di stampa non è corretto.Ho preso la precauzione di mettere questa stampa in un pragma critico in quanto altrimenti la stampa può essere selvaggiamente errata. – hajmola

risposta

0

Quindi ho finalmente capito il problema, anche se le specifiche OpenMP dicono che la clausola depend dovrebbe essere implementata con un punto di partenza e un intervallo, non è ancora stata implementata in gcc. Quindi attualmente confronta solo il punto di partenza dalla clausola depend (dipende (in: A [i-1: b + 2] [j-1: b + 2])) A [i-1] [j-1] in questo caso.

Inizialmente stavo confrontando gli elementi in diverse posizioni relative delle piastrelle. Ad esempio, confrontando (0,0) l'elemento con l'ultimo elemento della tessera, che non forniva conflitti con la dipendenza e quindi l'ordine casuale di esecuzione di varie attività.

L'implementazione corrente di gcc non interessa affatto l'intervallo fornito nella clausola.