2010-05-05 20 views
32

In OpenMP quando si utilizza omp sections, i thread verranno distribuiti ai blocchi all'interno delle sezioni o ciascun thread verrà assegnato a ciascuna sezione?Come funziona la direttiva SECTIONS in OpenMP?

Quando nthreads == 3:

#pragma omp sections 
{ 
    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 

    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 
} 

uscita:

id=1 
id=1 

Ma quando eseguo il seguente codice:

#pragma omp sections 
{ 
    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 

    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 
} 

#pragma omp sections 
{ 
    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 

    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 
} 

uscita:

id=1 
id=1 

id=2 
id=2 

Da questi output non riesco a capire quale sia il concetto di sezioni in OpenMP.

risposta

24

L'idea di sezioni parallele è di dare al compilatore un suggerimento che le varie sezioni (interne) possono essere eseguite in parallelo, ad esempio:

#pragma omp parallel sections 
{ 
    #pragma omp section 
    { 
     /* Executes in thread 1 */ 
    } 
    #pragma omp section 
    { 
     /* Executes in thread 2 */ 
    } 
    #pragma omp section 
    { 
     /* Executes in thread 3 */ 
    } 
    /* ... */ 
} 

Questo è un suggerimento al compilatore e non sempre garantito capita, anche se dovrebbe. Il tuo output è un po 'come ci si aspetta; dice che ci sono #sections in esecuzione nel thread id 1 e nel thread 2. L'ordine di output non è deterministico in quanto non si sa quale thread verrà eseguito per primo.

+0

-1 La tua risposta contiene molte inesattezze. Non puoi essere sicuro che diverse sezioni siano assegnate a thread differenti. L'ordine di output non è deterministico solo all'interno di un singolo costrutto 'sections', non tra due diverse' sezioni' (barriera implicita alla fine del costrutto) – Massimiliano

-3

Se si desidera davvero avviare thread diversi in sezioni diverse, la clausola indica al compilatore che i thread non devono attendere per entrare in una sezione.

#pragma omp parallel sections nowait 
{ 
    ... 
} 
+5

Questo è semplicemente sbagliato. 'nowait' significa rimuovere la barriera implicita alla fine di un costrutto di condivisione del lavoro. Non c'è barriera all'ingresso. – Massimiliano

+1

Sono d'accordo con Massimiliano; Inoltre, se provi a compilare nowait con il parallelo, dice che "nowait" non è valido per "le sezioni parallele omp ora" – Rotom92

0

nota che 'nowait' dice al compilatore che le discussioni non hanno bisogno di aspettare di uscita sezione. In Fortran 'nowait' va alla fine del ciclo o della sezione, il che rende questo più ovvio.

76

Sono abbastanza sorpreso che nessuna delle domande qui in realtà ha risposto all'OP. Poiché questo è uno dei primi risultati di Google, penso che sia importante chiarire l'argomento, specialmente per i principianti che potrebbero atterrare su questa pagina ed essere ancora più confusi. Inoltre, alcune delle risposte parlano della clausola nowait, che non è nemmeno menzionata nella domanda (immagino sia successo dopo una modifica della domanda). Questo rende le cose ancora più confuse.

L'OP è sorpreso dal fatto che ottiene lo stesso ID per sezioni diverse. Mentre wump è corretto, affermando che l'ordine non è deterministico, qui la ragione è molto più semplice: il codice pubblicato dall'OP non verrà mai eseguito in parallelo, perché la parola chiave "parallela" non appare, a meno che non sia racchiusa in un parallelo direttiva. Pertanto, non è un esempio utile. Il fatto che l'OP abbia ID diversi da 0 indica che probabilmente il suo codice era incorporato in una direttiva parallela. Tuttavia, questo non è chiaro dal suo post e potrebbe confondere i principianti.

L'esempio minima sensibile è (per il primo esempio inviato da PO):

#pragma omp parallel sections 
{ 
    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 

    #pragma omp section 
    { 
     printf ("id = %d, \n", omp_get_thread_num()); 
    } 
} 

Sulla mia macchina, questa stampa

id = 0, 
id = 1, 

mostrando che le due sezioni vengono eseguiti da diversi filettature. Vale la pena notare che tuttavia questo codice non può estrarre più parallelismo di due thread: se viene eseguito con più thread, gli altri thread non hanno alcun lavoro da fare e si limiteranno a rimanere inattivi.

4

Secondo OpenMP standard 3.1, sezione 2.5.2 (enfasi mia):

Le sezioni costrutto è un worksharing noniterative costrutto contiene una serie di blocchi strutturati che siano distribuiti tra ed eseguiti da le discussioni in una squadra. Ogni blocco strutturato è eseguito una volta da uno dei thread nel team nel contesto dell'implicazione implicita .

...

Ogni blocco strutturato in sezioni costrutto è preceduta da una direttiva sezione eccetto forse il primo blocco, per i quali una precedente direttiva sezione è facoltativa. Il metodo di pianificazione dei blocchi strutturati tra i thread nel team è l'implementazione definita. C'è una barriera implicita alla fine di un costrutto delle sezioni a meno che non venga specificata una clausola nowait.

Quindi, l'applicazione di queste regole al vostro caso, possiamo sostenere che:

  1. i diversi blocchi strutturati individuati in una direttiva sections sono eseguita una volta, da un thread. In altre parole si ha sempre quattro stampe, qualunque sia il numero di fili vengano eseguiti
  2. blocchi nella prima sections (in un ordine non deterministico) prima blocchi nella seconda sections (eseguita anche in modo non ordine deterministico). Questo è a causa della barriera implicito al termine dei lavori ripartizione costruisce
  3. la schedulazione viene attuazione definito, in modo che non può eventualmente controllare quali filo è stata assegnata una data sezione

L'output è quindi dovuto al modo in cui lo scheduler ha deciso di assegnare i diversi blocchi ai thread nel team.

10

cambiare la prima linea da

sezioni #pragma omp

in

#pragma omp sezioni parallele

direttiva "parallelo" assicura che il due sezioni sono assegnate a due tre Annunci. Poi, si riceverà il seguente output id = 0, id = 1,

2

Può essere utile aggiungere ulteriori informazioni alla linea di uscita e di aggiungere più sezioni (se avete la thread-count)

#pragma omp parallel sections 
{ 
    #pragma omp section 
    { 
     printf ("section 1 id = %d, \n", omp_get_thread_num()); 
    } 
    #pragma omp section 
    { 
     printf ("section 2 id = %d, \n", omp_get_thread_num()); 
    } 
    #pragma omp section 
    { 
     printf ("section 3 id = %d, \n", omp_get_thread_num()); 
    } 
} 

Poi si può ottenere l'output più interessanti come questo:

section 1 id = 4, 
section 3 id = 3, 
section 2 id = 1, 

che mostra come le sezioni possono essere eseguiti in qualsiasi ordine, da qualsiasi thread disponibili.

9

Ti manca la parola chiave parallel. La parola chiave parallel attiva l'apertura in parallelo.