2010-02-07 27 views
6

Soy bastante nuevo en OpenMP y estoy tratando de iniciar un hilo individual para procesar cada elemento en un conjunto 2D.Iniciando un hilo para cada bucle interno en OpenMP

Así que, esencialmente, esto:

for (i = 0; i < dimension; i++) { 
    for (int j = 0; j < dimension; j++) { 
     a[i][j] = b[i][j] + c[i][j]; 

Lo que estoy haciendo es lo siguiente:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic) 
    for (i = 0; i < dimension; i++) { 
     for (int j = 0; j < dimension; j++) { 
      a[i][j] = b[i][j] + c[i][j]; 

¿Este, de hecho, iniciar un hilo para cada elemento 2D o no? ¿Cómo probaría eso? Si es incorrecto, ¿cuál es la forma correcta de hacerlo? ¡Gracias!

Nota: El código se ha simplificado en gran medida

+0

posible que desee etiquetarlo con el lenguaje que está usando, aunque Tendría que eliminar una de las etiquetas existentes. –

+0

Buen punto mmyers - para referencia parece que está usando c/C++ (openMP es c/C++ y fortran solamente) –

Respuesta

7

Sólo el bucle externo es paralela en el ejemplo de código. Puede probar imprimiendo omp_get_thread_num() en el bucle interno y verá que, para un i dado, el número de subproceso es el mismo (por supuesto, esta prueba es demostrativa en lugar de definitiva ya que las diferentes ejecuciones darán resultados diferentes). Por ejemplo, con:

#include <stdio.h> 
#include <omp.h> 
#define dimension 4 

int main() { 
    #pragma omp parallel for 
    for (int i = 0; i < dimension; i++) 
     for (int j = 0; j < dimension; j++) 
      printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num()); 
    } 

me sale:

i=1, j=0, thread = 1 
i=3, j=0, thread = 3 
i=2, j=0, thread = 2 
i=0, j=0, thread = 0 
i=1, j=1, thread = 1 
i=3, j=1, thread = 3 
i=2, j=1, thread = 2 
i=0, j=1, thread = 0 
i=1, j=2, thread = 1 
i=3, j=2, thread = 3 
i=2, j=2, thread = 2 
i=0, j=2, thread = 0 
i=1, j=3, thread = 1 
i=3, j=3, thread = 3 
i=2, j=3, thread = 2 
i=0, j=3, thread = 0 

En cuanto al resto de su código, es posible que desee poner más detalles en una nueva pregunta (que es difícil saber a partir de la pequeña muestra), pero, por ejemplo, no puede poner private(j) cuando j solo se declara después. Es automáticamente privado en mi ejemplo anterior. Supongo que diff es una variable que no podemos ver en la muestra. Además, la variable de bucle i es automáticamente privado (de la version 2.5 spec - mismo en la especificación 3,0)

El bucle de iteración variable en el para-bucle de un favor o en paralelo para constructo es privado en que constructo .

Editar: Todo lo anterior es correcto para el código que usted y yo hemos mostrado, pero puede estar interesado en lo siguiente. Para la versión 3.0 de OpenMP (disponible en, por ejemplo, gcc version 4.4, pero no en la versión 4.3) existe una cláusula collapse donde puede escribir el código como lo ha hecho, pero con #pragma omp parallel for collapse (2) para paralelizar ambos bucles (consulte the spec).

Editar: OK, he descargado gcc 4.5.0 y corrió el código anterior, pero utilizando collapse (2) para obtener el siguiente resultado, que muestra el bucle interno ahora parallelized:

i=0, j=0, thread = 0 
i=0, j=2, thread = 1 
i=1, j=0, thread = 2 
i=2, j=0, thread = 4 
i=0, j=1, thread = 0 
i=1, j=2, thread = 3 
i=3, j=0, thread = 6 
i=2, j=2, thread = 5 
i=3, j=2, thread = 7 
i=0, j=3, thread = 1 
i=1, j=1, thread = 2 
i=2, j=1, thread = 4 
i=1, j=3, thread = 3 
i=3, j=1, thread = 6 
i=2, j=3, thread = 5 
i=3, j=3, thread = 7 

Comentarios here (búsqueda de "Soluciones provisionales") también son relevantes para soluciones alternativas en la versión 2.5 si desea paralelizar ambos bucles, pero la versión 2.5 especificada anteriormente es bastante explícita (consulte los ejemplos no conformes en la sección A.35).

+0

¡Gracias, el colapso fue el truco que estaba buscando! – achinda99

0

Puede tratar de usar formes omp paralelos anidados (después de la llamada omp_set_nested(1)), pero no son compatibles con todas las implementaciones de openmp.

así que supongo que para hacer algo de rejilla 2D y empezar todo de rosca en la parrilla de una sola para (ejemplo para la red fija hilo 4x4):

#pragma omp parallel for 
for(k = 0; k < 16; k++) 
{ 
    int i,j,i_min,j_min,i_max,j_max; 
    i_min=(k/4) * (dimension/4); 
    i_max=(k/4 + 1) * (dimension/4); 
    j_min=(k%4) * (dimension/4); 
    j_max=(k%4 + 1) * (dimension/4); 

    for(i=i_min;i<i_max;i++) 
     for(j=j_min;j<j_max;j++) 
     f(i,j); 

} 
Cuestiones relacionadas