2009-09-19 1 views

risposta

50

Io non credo che ci sia alcuna differenza, uno è una scorciatoia per l'altro. Sebbene la tua esatta implementazione possa gestirli diversamente.

I costrutti condivisione del lavoro parallele combinati sono un collegamento per specificare un costrutto parallelo contenente un costrutto worksharing e altre istruzioni. Le clausole consentite sono l'unione delle clausole consentite per i contrasti paralleli e di condivisione del lavoro.

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

le specifiche per OpenMP sono qui:

http://openmp.org/wp/openmp-specifications/

44

Questi sono equivalenti.

#pragma omp parallel genera un gruppo di thread, mentre #pragma omp for divide iterazioni di ciclo tra i thread generati. Puoi fare entrambe le cose contemporaneamente con la direttiva #pragma omp parallel for fusa.

+0

Nel mio codice sto usando questa stessa struttura. Tuttavia quando uso la clausola 'schedule (static, chunk)' per direttiva, ho un problema. Il codice funziona bene, ma quando sto invocando questo codice da un programma MPI, viene eseguito in un ciclo infinito. Il contatore di cicli è zero in tutte le iterazioni di questo ciclo. Ho il contatore del ciclo definito come privato nella direttiva '#pragma omp parallel'. Non ho idea del motivo per cui fallisce solo quando MPI sta invocando il codice. Sono abbastanza sicuro che ogni processo MPI è in esecuzione su un processore diverso del cluster, se questo è importante. Non ho idea se il programma sta causando il problema. –

+0

La stessa cosa funziona bene quando uso la direttiva '#pragma omp parallel for'. Ci dovrebbe essere qualche differenza. Aggiornamento –

+1

: A quanto pare, sto osservando questo problema solo quando utilizzo la clausola schedule, quindi suppongo che non dipenda dal fatto che io usi il parallelo combinato per o due direttive diverse. –

2

sto vedendo rigido differenti tempi di esecuzione quando prendo un ciclo for in g ++ 4.7.0 e utilizzando

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 (senza openmp) corre in 79 ms. il codice "parallelo per" viene eseguito in 29 ms. Se Tralascio il for e utilizzare #pragma omp parallel, il runtime spara fino a 179ms, che è più lento rispetto al codice seriale. (La macchina ha concorrenza hw di 8)

i link di codice per libgomp

+2

Penso che sia perché omp parallel esegue il ciclo in un thread separato senza dividerlo in thread, quindi il thread principale è in attesa del secondo thread finito. e il tempo passa alla sincronizzazione. – Antigluk

+6

Questo perché senza un '#pragma omp for' non vi è alcuna condivisione multi-thread del ciclo. Ma non era questo il caso degli OP, riprova con un altro '#pragma omp for' all'interno di' #pragm omp parallel' e dovrebbe essere simile (se non uguale) alla versione '#pragma omp parallel for' . –

+0

Vedo questa risposta come la migliore in quanto mostra che non sono "equivalenti" –

19

Ecco esempio di utilizzo separato parallel e forhere. In breve, può essere utilizzato per l'allocazione dinamica di matrici private di thread OpenMP prima di eseguire il ciclo for in più thread. E 'impossibile fare la stessa cosa di inizializzazione in parallel for caso.

UPD: Nell'esempio della domanda non vi è alcuna differenza tra il singolo pragma e due direttive. Ma in pratica si può fare un comportamento più consapevole del thread con paralleli separati e per direttive. Alcuni di codice, ad 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 
} 
4

Anche se entrambe le versioni del caso specifico sono equivalenti, come già detto in altre risposte, c'è ancora una piccola differenza tra di loro. La prima versione include una barriera implicita non necessaria, riscontrata alla fine di "omp for". L'altra barriera implicita può essere trovata alla fine della regione parallela. Aggiungere "nowait" a "omp for" renderebbe i due codici equivalenti, almeno da una prospettiva OpenMP.Dico questo perché un compilatore OpenMP potrebbe generare un codice leggermente diverso per i due casi.