2012-05-10 29 views
18

si uso paralelo bucles for anidados como esto:OpenMP paralelo bucles for anidados vs paralelo interno para

#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 
} 

es esto 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 
} 

es el paralelo externa para hacer otra cosa que creando una nueva tarea?

Respuesta

34

Si su compilador soporta OpenMP 3.0, puede utilizar la cláusula de 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 
} 

Si no (por ejemplo, sólo OpenMP 2.5 es compatible), hay una solución sencilla:

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

Puede habilitar el paralelismo anidado con omp_set_nested(1); y su código anidado omp parallel for funcionará, pero esa podría no ser la mejor idea.

Por cierto, ¿por qué la programación dinámica? ¿Se evalúa cada iteración de bucle en tiempo no constante?

+1

Estoy usando VS2008, así que no creo que pueda usar el colapso, pensé en hacerlo de la segunda forma que mencionaste, pero esperaba no tener que cambiar el código significativamente. Es para un rastreador de rayos, por lo que algunos rayos primarios pueden tardar hasta 10 veces más que otros. –

+0

Aparentemente incluso VS2010 solo admite OpenMP 2.0. –

+0

ok, lo implementé de la segunda manera, con suerte MS se pondrá al día eventualmente ... –

7

NO.

El primer #pragma omp parallel creará un equipo de subprocesos paralelos y el segundo intentará crear para cada uno de los subprocesos originales otro equipo, es decir, un equipo de equipos. Sin embargo, en casi todas las implementaciones existentes, el segundo equipo tiene solo un hilo: la segunda región paralela esencialmente no se usa. Por lo tanto, su código es más como equivalente 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 
    } 
} 

Si no quiere eso, pero sólo paralelizar el bucle interno, se puede hacer esto:

#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

Veo, lo consideré pero parece tan contra intuitivo. Entonces, si quiero un "paralelo para" sobre todas las iteraciones, debería poner el "paralelo para" en el ciclo interno. –

+0

@Bunnit No sé lo que quiere, pero agregué mi respuesta. – Walter

+0

@Bunnit Creo que mi segunda solución debe alcanzar al menos la misma velocidad que la segunda de Hrito Iliev, pero conceptualmente es mucho más clara. Si la carga de trabajo en el bucle interno no es muy diferente entre diferentes valores para 'y', la primera solución es incluso preferible. En todos los casos, se paralela el doble bucle en el sentido de que cada par ('x',' y') solo es envuelto una vez por todo el equipo de hilos. – Walter

Cuestiones relacionadas