omp parallel vs. omp parallel per


105

Qual è la differenza tra questi due?

[UN]

#pragma omp parallel
{ 
    #pragma omp for
    for(int i = 1; i < 100; ++i)
    {
        ...
    }
}

[B]

#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
   ...
}

Risposte:


65

Non credo che ci sia alcuna differenza, una è una scorciatoia per l'altra. Sebbene la tua implementazione esatta potrebbe gestirli in modo diverso.

I costrutti combinati di condivisione del lavoro parallela sono una scorciatoia per specificare un costrutto parallelo contenente un costrutto di condivisione del lavoro e nessun'altra istruzione. Le clausole ammesse sono l'unione delle clausole ammesse per i contratti paralleli e di condivisione del lavoro.

Tratto da http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

Le specifiche per OpenMP sono qui:

https://openmp.org/specifications/


66

Questi sono equivalenti.

#pragma omp parallelgenera un gruppo di thread, mentre #pragma omp fordivide le iterazioni del ciclo tra i thread generati. Puoi fare entrambe le cose contemporaneamente con la #pragma omp parallel fordirettiva fused .


Nel mio codice sto usando proprio questa struttura. Tuttavia, quando utilizzo la schedule(static, chunk)clausola per la direttiva, ottengo un problema. Il codice funziona bene, ma quando richiamo questo codice da un programma MPI, viene eseguito in un ciclo infinito. Il contatore del ciclo è zero in tutte le iterazioni di questo ciclo. Ho il contatore del ciclo definito come privato nella #pragma omp paralleldirettiva. Non ho idea del motivo per cui fallisce solo quando MPI richiama il codice. Sono in qualche modo sicuro che ogni processo MPI sia in esecuzione su un processore diverso del cluster, se ciò è importante. Non ho idea se la pianificazione sta causando il problema.
Rohit Banga

La stessa cosa funziona bene quando uso la #pragma omp parallel fordirettiva. Ci dovrebbe essere qualche differenza.
Rohit Banga

1
Aggiornamento: A quanto pare, sto osservando questo problema solo quando utilizzo la clausola di pianificazione, quindi immagino che non dipenda dal fatto che utilizzo il parallelo combinato per o due direttive diverse.
Rohit Banga

28

Ecco un esempio di utilizzo di separate parallele for qui . In breve, può essere utilizzato per l'allocazione dinamica di array privati ​​di thread OpenMP prima di eseguire il forciclo in diversi thread. È impossibile eseguire la stessa inizializzazione nel parallel forcaso.

UPD: Nell'esempio della domanda non c'è differenza tra un singolo pragma e due pragmi. Ma in pratica puoi rendere il comportamento più sensibile ai thread con le direttive parallele e for separate. Alcuni codici per esempio:

#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}

9

Sebbene entrambe le versioni dell'esempio specifico siano equivalenti, come già menzionato nelle altre risposte, c'è ancora una piccola differenza tra loro. La prima versione include una barriera implicita non necessaria, riscontrata alla fine di "omp for". L'altra barriera implicita si trova alla fine della regione parallela. Aggiungere "nowait" a "omp for" renderebbe i due codici equivalenti, almeno dal punto di vista di OpenMP. Dico questo perché un compilatore OpenMP potrebbe generare codice leggermente diverso per i due casi.


7

Vedo tempi di esecuzione nettamente diversi quando prendo un ciclo for in g ++ 4.7.0 e utilizzo

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;

for (int i = 0; i < 5000000; i++)
{
   double r1 = ((double)rand() / double(RAND_MAX)) * 5;
   double r2 = ((double)rand() / double(RAND_MAX)) * 5;
   x.push_back(r1);
   y.push_back(r2);
}

int sz = x.size();

#pragma omp parallel for

for (int i = 0; i< sz; i++)
   prod[i] = x[i] * y[i];

il codice seriale (no openmp) viene eseguito in 79 ms. il codice "parallelo per" viene eseguito in 29 ms. Se ometto fore uso #pragma omp parallel, il runtime arriva fino a 179 ms, che è più lento del codice seriale. (la macchina ha una concorrenza hardware di 8)

il codice si collega a libgomp


2
Penso che sia perché omp parallel esegue il ciclo in thread separati senza dividerlo in thread, quindi il thread principale è in attesa che il secondo thread sia finito. e il tempo spende per la sincronizzazione.
Antigluk

7
Questo perché senza un #pragma omp fornon c'è alcuna condivisione multi-thread del ciclo. Ma non era comunque il caso degli OP, riprova con un ulteriore #pragma omp forall'interno di #pragm omp parallele dovrebbe funzionare in modo simile (se non lo stesso) come la #pragma omp parallel forversione.
Christian Rau

2
Vedo questa risposta come la migliore in quanto mostra che non sono "equivalenti"
Scienziato fallito il

6

Ci sono ovviamente molte risposte, ma questa risponde molto bene (con la fonte)

#pragma omp fordelega solo parti del ciclo per thread diversi nel team corrente. Una squadra è il gruppo di thread che eseguono il programma. All'inizio del programma, il team è composto da un solo membro: il thread principale che esegue il programma.

Per creare un nuovo team di thread, è necessario specificare la parola chiave parallela. Può essere specificato nel contesto circostante:

#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}

e:

Cosa sono: parallelo, per e una squadra

La differenza tra parallel, parallel for e for è la seguente:

Un team è il gruppo di thread che vengono eseguiti attualmente. All'inizio del programma, il team è costituito da un unico thread. Un costrutto parallelo divide il thread corrente in un nuovo team di thread per la durata del blocco / istruzione successivo, dopodiché il team si fonde di nuovo in uno solo. for divide il lavoro del ciclo for tra i thread del team attuale.

Non crea thread, divide solo il lavoro tra i thread del team attualmente in esecuzione. parallel for è un'abbreviazione per due comandi contemporaneamente: parallel e for. Parallel crea una nuova squadra e per le divisioni quella squadra gestisce diverse parti del ciclo. Se il tuo programma non contiene mai un costrutto parallelo, non c'è mai più di un thread; il thread principale che avvia il programma e lo esegue, come nei programmi non threading.

https://bisqwit.iki.fi/story/howto/openmp/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.