omp - ¿Cómo funciona la directiva SECTIONS en OpenMP Distribuir?
pragma omp critical (8)
Cambiar la primera línea de
#pragma omp sections
dentro
#pragma omp secciones paralelas
La directiva "paralela" garantiza que las dos secciones estén asignadas a dos hilos. Luego, recibirá la siguiente salida id = 0, id = 1,
En OpenMP cuando se usan omp sections
, ¿se distribuirán los subprocesos a los bloques dentro de las secciones , o se asignará cada subproceso a cada sección?
Cuando 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());
}
}
Salida:
id=1
id=1
Pero cuando ejecuto el siguiente código:
#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());
}
}
Salida:
id=1
id=1
id=2
id=2
A partir de estos resultados, no puedo entender cuál es el concepto de secciones en OpenMP.
De acuerdo con el estándar 3.1 de OpenMP , sección 2.5.2 (énfasis mío):
El constructo de secciones es un constructo de trabajo compartido no iterativo que contiene un conjunto de bloques estructurados que se distribuirán y ejecutarán entre los hilos de un equipo . Cada bloque estructurado se ejecuta una vez por uno de los hilos del equipo en el contexto de su tarea implícita.
...
Cada bloque estructurado en el constructo de secciones está precedido por una directiva de sección, excepto posiblemente el primer bloque, para el cual una directiva de sección precedente es opcional. El método de programación de los bloques estructurados entre los hilos en el equipo está definido por la implementación . Existe una barrera implícita al final de una construcción de secciones a menos que se especifique una cláusula nowait.
Entonces, al aplicar estas reglas a su caso, podemos argumentar que:
- los diferentes bloques estructurados identificados en una directiva de
sections
se ejecutan una vez, por un hilo . En otras palabras, siempre tiene cuatro impresiones, cualquiera que sea el número de hilos - los bloques en las primeras
sections
se ejecutarán (en un orden no determinista) antes de los bloques en las segundassections
(también ejecutados en un orden no determinista). Esto se debe a la barrera implícita al final de las construcciones de trabajo compartido - la programación es implementación definida , por lo que no puede controlar qué subproceso se le ha asignado una sección determinada
Por lo tanto, su resultado se debe a la forma en que su planificador decidió asignar los diferentes bloques a los hilos en el equipo.
El código publicado por el OP nunca se ejecutará en paralelo, porque la palabra clave parallel
no aparece . El hecho de que el OP obtuvo identificadores diferentes de 0 muestra que probablemente su código estaba incrustado en una directiva paralela. Sin embargo, esto no está claro en su publicación, y podría confundir a los principiantes.
El ejemplo sensible mínimo es (para el primer ejemplo publicado por el OP):
#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());
}
}
En mi máquina, esto imprime
id = 0,
id = 1,
mostrando que las dos secciones están siendo ejecutadas por diferentes hilos.
Sin embargo, vale la pena señalar que este código no puede extraer más paralelismo que dos subprocesos: si se ejecuta con más subprocesos, los otros subprocesos no tienen ningún trabajo que hacer y se quedarán inactivos.
La idea de las secciones paralelas es dar al compilador una pista de que las diversas secciones (internas) se pueden realizar en paralelo, por ejemplo:
#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 */
}
/* ... */
}
Esto es una pista para el compilador y no está garantizado que suceda, aunque debería. Tu producción es algo de lo que se espera; dice que hay #secciones que se están ejecutando en el id. de subproceso 1, y en el subproceso 2. El orden de salida no es determinista ya que no se sabe qué subproceso se ejecutará primero.
Puede ser útil agregar más información a la línea de salida y agregar más secciones (si tiene el número de subprocesos)
#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());
}
}
Entonces puede obtener un resultado más interesante como este:
section 1 id = 4,
section 3 id = 3,
section 2 id = 1,
que muestra cómo las secciones se pueden ejecutar en cualquier orden, por cualquier hilo disponible.
Si realmente desea iniciar diferentes hilos en diferentes secciones, la cláusula nowait
le dice al compilador que los hilos no necesitan esperar para ingresar a una sección.
#pragma omp parallel sections nowait
{
...
}
Te estás perdiendo la palabra clave parallel
. La palabra clave parallel
activa la ejecución de openmp en paralelo.
Tenga en cuenta que ''nowait'' le dice al compilador que los hilos no necesitan esperar para salir de la sección. En Fortran, "nowait" va al final del ciclo o sección, lo que lo hace más obvio.