while una repetitivos programacion piramide lenguaje hacer for estructuras estructura ejercicios doble condicion con como ciclos ciclo asteriscos anidar anidados anidado anidadas anidada c++ loops parallel-processing openmp

c++ - una - ¿Cómo maneja OpenMP los bucles anidados?



ejercicios de estructuras anidadas en c++ (3)

¿El siguiente código simplemente paraleliza los primeros bucles (externos) o paraleliza todo el bucle anidado?

#pragma omp parallel for for (int i=0;i<N;i++) { for (int j=0;j<M;j++) { //do task(i,j)// } }

Solo quiero asegurarme de que el código anterior paralelice todo el for-loop anidado (por lo tanto, un hilo directamente relacionado con la tarea (i, j)), o solo paraleliza el for-loop externo (por lo tanto, asegura que, para cada parrallel hilo con índice de bucle i, su bucle interno se realizará de forma secuencial en un único hilo, lo cual es muy importante).


Las líneas que ha escrito pondrán en paralelo solo el bucle externo. Para poner en paralelo ambos, debe agregar una cláusula de collapse :

#pragma omp parallel for collapse(2) for (int i=0;i<N;i++) { for (int j=0;j<M;j++) { //do task(i,j)// } }

Es posible que desee verificar las especificaciones de OpenMP 3.1 (sección 2.5.1) para obtener más detalles.


OpenMP solo paraleliza el ciclo al lado del pragma. También puede paralelizar el lazo interno si lo desea, pero no se realizará automáticamente.


Podrás entender mejor esto con el siguiente ejemplo. Hagamos esto con dos hilos.

#pragma omp parallel for num_threads(2) for(int i=0; i< 3; i++) { for (int j=0; j< 3; j++) { printf("i = %d, j= %d, threadId = %d /n", i, j, omp_get_thread_num()); } }

entonces el resultado será,

i = 0, j= 0, threadId = 0 i = 0, j= 1, threadId = 0 i = 0, j= 2, threadId = 0 i = 1, j= 0, threadId = 0 i = 1, j= 1, threadId = 0 i = 1, j= 2, threadId = 0 i = 2, j= 0, threadId = 1 i = 2, j= 1, threadId = 1 i = 2, j= 2, threadId = 1

Eso significa que, cuando agrega #pragma omp parallel para al ciclo for superior, el índice de ese ciclo for se divide entre los hilos. Como puede ver, cuando el índice de i es el mismo, la identificación del hilo también es la misma.

En lugar de eso, podemos hacer un paralelo con las combinaciones que tenemos en un ciclo anidado. En este ejemplo, podemos tener las siguientes combinaciones de i y j.

i = 0, j= 0 i = 0, j= 1 i = 0, j= 2 i = 1, j= 0 i = 1, j= 1 i = 1, j= 2 i = 2, j= 0 i = 2, j= 1 i = 2, j= 2

Para paralelizar la combinación de códigos, podemos agregar la palabra clave de colapso de la siguiente manera.

#pragma omp parallel for num_threads(2) collapse(2) for(int i=0; i< 3; i++) { for (int j=0; j< 3; j++) { printf("i = %d, j= %d, threadId = %d /n", i, j, omp_get_thread_num()); } }

entonces el resultado será el siguiente.

i = 0, j= 0, threadId = 0 i = 0, j= 1, threadId = 0 i = 1, j= 2, threadId = 1 i = 2, j= 0, threadId = 1 i = 2, j= 1, threadId = 1 i = 2, j= 2, threadId = 1 i = 0, j= 2, threadId = 0 i = 1, j= 0, threadId = 0 i = 1, j= 1, threadId = 0

Luego puede ver que a diferencia de antes, para el mismo índice i, puede haber diferentes identificadores de subprocesos (cuando (i = 1 yj = 2 threadId = 1) también (i = 1 y j = 0 threadId = 0)). Eso significa que en este escenario, las combinaciones de i y j se dividen entre los hilos.