2012-05-10 11 views
18

se uso annidati parallelo per cicli come questo:openMP nidificato parallelo per cicli vs parallelo interno per

#pragma omp parallel for schedule(dynamic,1) 
for (int x = 0; x < x_max; ++x) { 
    #pragma omp parallel for schedule(dynamic,1) 
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here 
    } 
//IMPORTANT: no code in here 
} 

è questo equivale a:

for (int x = 0; x < x_max; ++x) { 
    #pragma omp parallel for schedule(dynamic,1) 
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here 
    } 
//IMPORTANT: no code in here 
} 

È il parallelo esterno per fare qualcosa di diverso creando un nuovo compito?

risposta

34

Se il compilatore supporta OpenMP 3.0, è possibile utilizzare la clausola collapse:

#pragma omp parallel for schedule(dynamic,1) collapse(2) 
for (int x = 0; x < x_max; ++x) { 
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here 
    } 
//IMPORTANT: no code in here 
} 

Se non (ad esempio solo OpenMP 2.5 è supportato), c'è una soluzione semplice:

01.235.

È possibile abilitare il parallelismo nidificato con omp_set_nested(1); e il codice nidificato omp parallel for funzionerà ma potrebbe non essere l'idea migliore.

A proposito, perché la pianificazione dinamica? Ogni iterazione del ciclo viene valutata in un tempo non costante?

+1

Sto usando VS2008 quindi non credo di poter usare il collasso, ho pensato di farlo nel modo in cui hai menzionato, ma speravo di non dover cambiare il codice in modo significativo. È per un raggio ray tracer quindi alcuni raggi primari possono richiedere fino a 10 volte più a lungo rispetto ad altri –

+0

Apparentemente anche VS2010 supporta solo OpenMP 2.0. –

+0

ok, l'ho implementato nel secondo modo, si spera che MS raggiunga finalmente ... –

7

NO.

Il primo #pragma omp parallel creerà un team di thread paralleli e il secondo tenterà quindi di creare per ciascuno dei thread originali un altro team, ovvero una squadra di team. Tuttavia, su quasi tutte le implementazioni esistenti, la seconda squadra ha solo un thread: la seconda regione parallela non viene sostanzialmente utilizzata. Così, il codice è più simile equivale a

#pragma omp parallel for schedule(dynamic,1) 
for (int x = 0; x < x_max; ++x) { 
    // only one x per thread 
    for (int y = 0; y < y_max; ++y) { 
     // code here: each thread loops all y 
    } 
} 

Se non si vuole questo, ma parallelizzare solo il ciclo interno, si può fare questo:

#pragma omp parallel 
for (int x = 0; x < x_max; ++x) { 
    // each thread loops over all x 
#pragma omp for schedule(dynamic,1) 
    for (int y = 0; y < y_max; ++y) { 
     // code here, only one y per thread 
    } 
} 
+0

Vedo, l'ho considerato ma sembra così contro intuitivo. Quindi se voglio un 'parallelo per' su tutte le iterazioni dovrei mettere il 'parallelo per' sul ciclo interno? –

+0

@Bunnit Non so cosa vuoi, ma ho aggiunto alla mia risposta. – Walter

+0

@Bunnit Penso che la mia seconda soluzione dovrebbe raggiungere almeno la stessa velocità del secondo di Hrito Iliev, ma concettualmente è molto più chiaro. Se il carico di lavoro nel ciclo interno non è molto diverso tra i diversi valori di 'y', la prima soluzione è persino preferibile. In tutti i casi, si parallelizza il doppio ciclo nel senso che ogni coppia ('x',' y') viene invocata una sola volta dall'intero team di thread. – Walter