OpenMP: Paralelización Simplificada para Sistemas de Memoria Compartida
Clasificado en Informática
Escrito el en español con un tamaño de 36,76 KB
¿Qué es OpenMP?
OpenMP (Open Multi-Processing) es una API que permite la expresión de programas paralelos portables, de memoria compartida, a partir de programas secuenciales, con independencia del lenguaje (actualmente, en C, C++ y Fortran).
- A partir de la versión 4.0, OpenMP proporciona soporte para la explotación de sistemas híbridos o heterogéneos (CPU + GPU…).
- Es un modelo de programación paralela, de paralelismo explícito (paralelización dirigida por el programador), de memoria compartida.
Aproximación OpenMP
- La idea consiste en partir de un programa base secuencial.
- En una fase posterior, asumiendo un modelo de memoria compartida, se anota el programa base secuencial, especificando aspectos de cómo, desde un punto de vista de paralelismo.
- La aproximación se encuadra dentro del paradigma paralelismo explícito (es el programador el que decide, en este caso en la fase de anotado, qué debe ser ejecutado en paralelo y cómo).
- Además, el lenguaje base más la notación de anotación pueden ser utilizados conjuntamente a modo de lenguaje de programación paralela.
¿Qué no es OpenMP?
- No es un sistema de paralelización automática.
- Una implementación correcta de la especificación OpenMP, no tiene por qué identificar problemas de dependencias de datos, de condiciones de carrera, o desituaciones de abrazo mortal, que pueden darse en programas correctamente anotados, según la especificación OpenMP.
- Una implementación correcta de la especificación OpenMP, no tiene por qué identificar anotaciones que no son correctas, según la especificación OpenMP.
- No tiene por qué estar implementado de la misma forma en todas sus implementaciones.
- No tiene por qué entenderse que es, necesariamente, la forma más efectiva de explotar un sistema de memoria compartida.
Componentes de la API OpenMP
La API OpenMP comprende:
- Un conjunto de directivas.
- Un conjunto de rutinas de librería.
- Un conjunto de variables de entorno.
Directivas: parallel
, for
, sections
, task
, barrier
, critical
, flush
…
Rutinas de librería: omp_get_max_threads()
, omp_set_nested()
, omp_get_wtime()
…
Variables de entorno: OMP_NUM_THREADS
, OMP_NESTED
…
Conceptos OpenMP
Anotación OpenMP: Texto, añadido a un programa base secuencial, escrito en un lenguaje base secuencial (C, C++ o Fortran), para especificar aspectos de comportamiento paralelo, según la especificación OpenMP. Comprende directivas e invocaciones a rutinas de la librería de tiempo de ejecución de OpenMP.
Programa
Directiva OpenMP: Anotación, dirigida al compilador, que especifica aspectos de comportamiento paralelo, típicamente en relación con un bloque estructurado, según la especificación OpenMP. Una directiva OpenMP puede estar asociada o no a código del programa base secuencial.
Categorías de asociaciones de directivas:
none
block-associated
: El código de usuario asociado debe ser un bloque estructurado.loop-associated
: El código de usuario asociado debe ser un anidamiento de bucles canónicos.declaration-associated
delimited
separating
Bloque estructurado: Una sentencia ejecutable, posiblemente compuesta, con una única entrada (la primera sentencia de la composición) y una única salida (la última sentencia de la composición), o una construcción OpenMP.
Anidado de bucles canónico: Anidado de bucles que cumple las reglas y restricciones definidas en la sección 4.4.1 de la especificación.
Construcción OpenMP: Conjunto formado por una directiva ejecutable OpenMP y la sentencia ejecutable, bucle o bloque estructurado, sobre la que tiene efecto, si la hay.
Sintaxis de una directiva OpenMP
- Las directivas de OpenMP se especifican mediante una especificación de directiva.
- Una especificación de directiva consiste en el especificador de directiva y cualquier cláusula que pueda estar opcionalmente asociada con la directiva de OpenMP.
- El orden en que las cláusulas aparecen en las directivas no es significativo, a menos que se especifique lo contrario.
- En C y C++ las directivas OpenMP pueden especificarse haciendo uso de la directiva de preprocesamiento pragma, según la especificación informal: #pragma omp directive-specifier [clause[[,] clause]…] new-line directive-specifier is: directive-name or directive-name[ (directive-arguments) ]
Modelo de Programación
De paralelismo explícito.
El programador decide qué debe ser ejecutado en paralelo y cómo.
De memoria compartida.
Los datos elaborados por un hilo de ejecución pueden ser puestos a disposición de otro haciendo uso de operaciones de acceso a memoria sobre variables compartidas.
Con soporte para paralelismo de datos y de tareas.
Con soporte para expresar que un mismo tratamiento tiene que aplicarse, en paralelo, sobre diferentes datos, y con soporte para expresar que diferentes tratamientos tienen que aplicarse, en paralelo, sobre diferentes datos.
Con soporte para paralelismo irregular.
Con soporte para la especificación de unidades de trabajo cuya ejecución puede llegar a ser diferida.
De paralelismo dinámico.
El número de hilos de ejecución, que cooperan en la ejecución de un programa, puede fijarse en tiempo de ejecución (sin requerir recompilar el programa). El número de hilos de ejecución, que cooperan en la ejecución de un programa, puede variarse de una parte del programa a otra.
Modelo de Ejecución
Escenarios de ejecución
Típicamente, la ejecución de un programa OpenMP tiene lugar en el contexto de ejecución proporcionado por un único proceso, y bajo la supervisión de un único sistema operativo.
Previamente a la versión 4.0, las ejecuciones de un programa OpenMP solían tener lugar sobre dos tipos de sistema:
- Sobre un procesador multinúcleo.
- Sobre un sistema multi-zócalo (típicamente multi-núcleo).
A partir de la especificación 4.0, un programa OpenMP puede, además, descargar procesamiento sobre dispositivos aceleradores.
De modo que, a partir de la versión 4.0, los programas OpenMP pueden llegar a sacar provecho de los tipos de sistema:
- procesador multinúcleo + aceleradores.
- sistema multi-zócalo + aceleradores.
En este curso, obviaremos la parte de OpenMP que permite la explotación de aceleradores.
Terminología OpenMP
Thread (Hilo)
Una entidad de ejecución con una pila y memoria privada de hilo (threadprivate) asociada.OpenMP thread (Hilo de OpenMP)
Un hilo gestionado por el sistema de tiempo de ejecución de OpenMP.Processor (Procesador)
Unidad de hardware definida por la implementación, en la cual uno o más hilos de OpenMP pueden ejecutarse.Device (Dispositivo)
Un motor lógico de ejecución definido por la implementación, que puede contener uno o más procesadores.Host device (Dispositivo anfitrión)
El dispositivo en el cual comienza la ejecución del programa OpenMP.Target device (Dispositivo objetivo)
Un dispositivo con respecto al cual el dispositivo actual realiza una operación, según lo especificado por una construcción de dispositivo o una rutina de memoria de dispositivo OpenMP.Las abstracciones thread y task
El modelo de ejecución de OpenMP se describe en términos de dos abstracciones fundamentales: el thread (hilo de ejecución) y la task (tarea).
Thread
Unidad de control de ejecución, dotada de una pila de ejecución propia y de una memoria asociada (the threadprivate memory), que, típicamente, comparte, con otros threads, un mismo contexto de proceso (espacio de direcciones lógico, contexto de entrada/salida,…).
Task
Unidad de trabajo, constituida por una instancia de código, un entorno de datos propio y un conjunto de variables de control internas (de nivel de tarea) propio, cuya ejecución, controlada por un thread o conjunto de threads (thread team), puede ser inmediata o diferida, y suspendida y resumida.
Generalidades sobre threads
Creación.
Se crean en grupos (teams), por indicación explícita del programador, típicamente haciendo uso de la directiva parallel, para ejecutar una tarea o conjunto de tareas, especificadas de manera implícita o explicita por el propio programador.
Gestión según el modelo fork-join (master thread)
El thread que encuentra una construcción parallel crea un team, formado por él mismo y cero o más threads adicionales, convirtiéndose en el primary del nuevo team (fork). Sólo el primary thread sigue en ejecución más allá de la construcción parallel (join). Soportan paralelismo dinámico.
El número de threads, que cooperan en la ejecución de una parte de un programa, puede fijarse en tiempo de ejecución (sin requerir recompilar el programa). Además, puede variarse de una parte del programa a otra.
Soportan paralelismo anidado.
Dependiendo de la implementación, se contempla la posibilidad de paralelismo anidado.
Generalidades sobre tasks
Creación implícita.
De manera implícita, se crean, por grupos, por indicación expresa del programador, típicamente haciendo uso de la construcción parallel.
Creación explícita.
De manera explícita, se crean, por indicación expresa del programador, típicamente haciendo uso de la construcción task.
Vinculación a threads.
Las tasks generadas de manera implícita, en relación con una construcción parallel, se reparten entre los diferentes threads miembros del team. Una task generada de manear explícita, a partir de una construcción task, se asigna a uno de los threads del team, en función de su disponibilidad.
Anidado.
Pueden generarse de forma anidada.
Ejecución y planificación.
En general, una task puede ser ejecutada de manera inmediata o diferida. Puede ser suspendida, en task scheduling points, para poder ejecutar una tarea diferente. Y, de haber sido suspendida, será resumida, en el caso de una tied task, por el thread al que fue asignada, y en el caso de una untied task, por alguno de los threads del team.
Modelo de ejecución
Un programa OpenMP empieza su ejecución, en el host device, con un único thread (el initial thread), ejecutando la tarea, creada de manera implícita a partir del código del programa, conocida como la initial task.
Cuando un thread encuentra una construcción parallel, crea un team de threads, formado por él mismo y cero o más threads adicionales, y se convierte en el primary thread del nuevo team.
Diferentes construcciones dan lugar a la creación de tasks, que se distribuyen entre los diferentes threads del team, a los cuales pueden quedar o no vinculadas.
Sólo el primary thread sigue en ejecución más allá de la construcción parallel.
Variables de Control Internas
Concepto de variable de control interna
Una implementación OpenMP debe comportarse como si tuviera variables de control internas (ICVs) que determinaran el comportamiento de un programa OpenMP.
Reciben valor, en diferentes momentos, durante la ejecución de un programa.
Son inicializadas por la propia implementación, y se les puede asignar valor a partir de variables de entorno y haciendo uso de rutinas específicas de la API OpenMP.
Su valor se puede consultar, única y exclusivamente, mediante la invocación de rutinas específicas de la API OpenMP.
ICVs scopes
OpenMP define variables de control internas (ICVs) a diferentes niveles, en el sentido de que tienen ámbito diferente (scope). OpenMP ICVs scopes:
- global (for the whole of the program)
- device
- implicit task
- data environment
Generación de Paralelismo
Construcciones de generación de paralelismo La API OpenMP define las construcciones de generación y control de paralelismo:
- parallel
- teams
- simd
- masked
La construcción parallel
Summary
La construcción parallel crea un equipo de hilos OpenMP que ejecutan la región.
Syntax
#pragma omp parallel [clause[[,] clause]…] new-line structured-block
Clauses :
allocate,copyin,default, firstprivate ,if ,num_threads ,private ,proc_bind reduction ,shared
Vinculación
El conjunto de hilos vinculado a una región paralela es el hilo que la encuentra. Este hilo se convierte en el hilo maestro del nuevo equipo.Semántica
Cuando un hilo encuentra una construcción parallel, se crea un equipo de hilos para ejecutar la región paralela. El hilo que encontró la construcción parallel se convierte en el hilo principal del nuevo equipo, con un número de hilo igual a cero durante la ejecución de la nueva región paralela.Todos los hilos del nuevo equipo, incluido el hilo principal, ejecutan la región. Una vez creado el equipo, el número de hilos en él permanece constante durante toda la región paralela.
El hilo que encuentra la construcción genera un conjunto de tareas implícitas, cuyo número es igual al número de hilos en el equipo. El bloque estructurado...
Al final de una región paralela ocurre una barrera implícita. Después del final de una región paralela, solo el hilo principal del equipo reanuda la ejecución
Número de threads para parallel
Cuando la ejecución encuentra una directiva parallel, el número de hilos para la región se determina usando:
- El valor de la cláusula if o num_threads (si existe).
- El contexto paralelo actual.
- Los valores de las ICVs: nthreads-var, dyn-var, thread-limit-var y max-active-level-var.
Las expresiones de las cláusulas if y num_threads se evalúan en el contexto fuera de la construcción parallel.
El número de hilos se determina según el Algoritmo 2.1 (página 226, OpenMP API versión 5.2 November 2021 ).
Construcciones de Work-Distribution
Construcción de work-distribution
Una construcción de distribución de trabajo distribuye la ejecución de la región correspondiente entre los hilos del conjunto de hilos vinculados.
Los hilos ejecutan porciones de la región en el contexto de las tareas implícitas que cada uno está ejecutando.
Cada región de distribución de trabajo debe ser encontrada por todos los hilos del conjunto de hilos vinculados o por ninguno, a menos que...
La secuencia de regiones de distribución de trabajo encontradas, que comparten el mismo conjunto de hilos vinculados, debe ser la misma para todos los hilos en dicho conjunto.
Work-distribution y worksharing
Una construcción de distribución de trabajo es worksharing si el conjunto de hilos vinculados es un equipo de hilos.
Una región worksharing no tiene barrera al principio; sin embargo, existe una barrera implícita al final de la región worksharing, a menos que se especifique una cláusula nowait.
La secuencia de regiones worksharing y regiones de barrera que se vinculan al mismo equipo de hilos debe ser la misma para cada hilo en el equipo.
Construcciones de work-distribution La API OpenMP define las siguientes construcciones de work-distribution:
- single - scope - sections - workshare (only Fortran) - worksharing-loop (for in C and do in Fortran) - distribute - loop
La construcción single
Summary
La construcción single especifica que el bloque estructurado asociado es ejecutado por solo uno de los hilos en el equipo (no necesariamente el hilo principal), en el contexto de su tarea implícita.
Syntax
#pragma omp single [clause[[,] clause]…] new-line structured-block
Clauses
allocate ,copyprivate ,firstprivate ,nowait, private
Binding
El conjunto de hilos vinculado para una región single es el equipo actual. Una región single se vincula a la región paralela que la envuelve más internamente. Solo los hilos del equipo que ejecutan la región paralela vinculada participan en la ejecución del bloque estructurado y la barrera implícita de la región single, si la barrera no es eliminada por una cláusula nowait.
Semantics
La construcción single especifica que el bloque estructurado asociado es ejecutado por solo uno de los hilos en el equipo (no necesariamente el hilo principal), en el contexto de su tarea implícita. El método para elegir un hilo para ejecutar el bloque estructurado cada vez que el equipo encuentra la construcción está definido por la implementación.
Existe una barrera implícita al final de la región single, si no se especifica la cláusula nowait.
La construcción sections
Summary
La construcción sections es una construcción worksharing no iterativa que contiene un conjunto de secuencias de bloques estructurados que deben ser distribuidos entre los hilos de un equipo y ejecutados por ellos.
Syntax
#pragma omp sections [clause[[,] clause]…] new-line {
[#pragma omp section new-line] structured-block-sequence
#pragma omp section new-line structured-block-sequence]… }
Clauses
allocate ,firstprivate, lastprivate, nowait, private reduction
Binding
El conjunto de hilos vinculado para una región sections es el equipo actual. Una región sections se vincula a la región paralela que la envuelve más internamente. Solo los hilos del equipo que ejecutan la región paralela vinculada participan en la ejecución de las secuencias de bloques estructurados y la barrera implícita de la región sections, si la barrera no es eliminada por una cláusula nowait.
Semantics
La construcción sections es una construcción worksharing no iterativa que contiene un conjunto de secuencias de bloques estructurados que deben ser distribuidas entre los hilos de un equipo y ejecutadas por ellos. Cada secuencia de bloque estructurado es ejecutada una vez por uno de los hilos en el equipo, en el contexto de su tarea implícita.
Existe una barrera implícita al final de una construcción sections, a menos que se especifique una cláusula nowait. Cada secuencia de bloque estructurado en la construcción sections está precedida por una directiva section, excepto posiblemente la primera secuencia, para la cual la directiva section precedente es opcional.
El método de programación de las secuencias de bloques estructurados entre los hilos en el equipo está definido por la implementación.
La construcción worksharing-loop
Summary
La construcción worksharing-loop especifica que las iteraciones de uno o más bucles asociados se ejecutarán en paralelo por los hilos del equipo, en el contexto de sus tareas implícitas.
Syntax
#pragma omp for [clause[[,] clause]…] new-line loop-nest
Clauses : allocate, collapse ,firstprivate, lastprivate, linear, nowait ,order ,ordered private, reduction ,schedule
Binding
El conjunto de hilos vinculado para una región worksharing-loop es el equipo actual. Una región worksharing-loop se vincula a la región paralela que la envuelve más internamente. Solo los hilos que ejecutan la región paralela vinculada participan en la ejecución de las iteraciones del bucle y la barrera implícita de la región worksharing-loop, cuando esa barrera no es eliminada por una cláusula nowait.
Semantics
La construcción worksharing-loop es una construcción worksharing que especifica que las iteraciones de uno o más bucles asociados se ejecutarán en paralelo por los hilos del equipo, en el contexto de sus tareas implícitas. Las iteraciones se distribuyen entre los hilos que ya existen en el equipo que está ejecutando la región paralela a la que se vincula la región worksharing-loop. Cada hilo ejecuta los fragmentos asignados en el contexto de su tarea implícita. Las iteraciones de un fragmento dado se ejecutan en orden secuencial.
La cláusula collapse puede usarse para especificar cuántos bucles están asociados con la construcción worksharing-loop.
Si se especifica, la cláusula schedule determina la programación de las iteraciones lógicas asociadas con la construcción. Es decir, determina la división de las iteraciones en fragmentos y cómo esos fragmentos se asignan a los hilos. Si no se especifica la cláusula schedule, la programación está definida por la implementación.
Construcciones de Tasking
Concepto de construcción de tasking
En OpenMP, las construcciones de tasking sirven para crear tasks, de forma explícita, y controlar su ejecución.
Construcciones de tasking
OpenMP especifica varias construcciones de tasking. Entre ellas:
- task.
- taskloop.
- taskyield.
La construcción task
La construcción task define una tarea explícita.
Syntax
#pragma omp task [clause[[,] clause]…] new-line
structured-block
Clauses
affinity ,allocate ,default, depend ,detach ,final, firstprivate, if, in_reduction ,mergeable, priority, private, shared, untied
Binding
El conjunto de hilos vinculado a la región task es el equipo actual. Una región task se vincula a la región paralela que la envuelve más internamente.
Semantics
Cuando un hilo encuentra una construcción task, se genera una tarea explícita a partir del código del bloque estructurado asociado.
El entorno de datos de la tarea se crea de acuerdo con:
- Las cláusulas de atributo de compartición de datos en la construcción task.
- Las ICVs (variables de control de implementación) relacionadas con el entorno de datos.
- Cualquier valor por defecto que aplique.
El entorno de datos de la tarea se destruye cuando se completa la ejecución del código del bloque estructurado asociado.
El hilo que encuentra la tarea puede ejecutarla inmediatamente o diferir su ejecución. En este último caso, cualquier hilo del equipo puede ser asignado para ejecutar la tarea.
La finalización de la tarea se puede garantizar utilizando construcciones y cláusulas de sincronización de tareas. Si una construcción task se encuentra durante la ejecución de una tarea externa, la región de tarea generada correspondiente a esta construcción no forma parte de la región de la tarea externa, a menos que la tarea generada sea una tarea incluida (included task).
Un hilo que encuentra un punto de planificación de tareas dentro de la región de tarea puede suspender temporalmente la ejecución de dicha
La construcción taskyield región.
Summary
La región taskyield incluye un punto explícito de planificación de tareas en la región de tarea actual.
Syntax
#pragma omp taskyield new-line
Binding
Una región taskyield se vincula a la región de tarea actual. El conjunto de hilos vinculado a la región taskyield es el equipo actual.
Semantics
Semántica:
La región taskyield incluye un punto explícito de planificación de tareas dentro de la región de tarea actual.
Task scheduling
Cada vez que un hilo alcanza un punto de planificación de tareas, la implementación puede hacer que realice un cambio de tarea, comenzando o reanudando la ejecución de una tarea diferente vinculada al equipo actual. Los puntos de planificación de tareas están implícitos en las siguientes ubicaciones:
- Durante la generación de una tarea explícita.
- Justo después de la generación de una tarea explícita.
- Después de completar el bloque estructurado asociado con una tarea.
- En regiones taskyield.
- En regiones taskwait.
- Al final de una región taskgroup.
- En una región de barrera implícita.
- En una región de barrera explícita.
Reaching task scheduling points
Cuando un hilo encuentra un punto de planificación de tareas, puede realizar una de las siguientes acciones, sujeto a las Restricciones de Planificación de Tareas (página 273, OpenMP API Versión 5.2, noviembre 2021):
- Comenzar la ejecución de una tarea tied vinculada al equipo actual.
- Reanudar cualquier región de tarea suspendida, vinculada al equipo actual, a la que esté tied.
- Comenzar la ejecución de una tarea untied vinculada al equipo actual.
- Reanudar cualquier región de tarea untied suspendida, vinculada al equipo actual.
Nota:
Los puntos de planificación de tareas dividen dinámicamente las regiones de tareas en partes. Cada parte se ejecuta de manera ininterrumpida desde el principio hasta el final. Las diferentes partes de la misma región de tarea se ejecutan en el orden en que se encuentran.
En ausencia de construcciones de sincronización de tareas, el orden en que un hilo ejecuta partes de diferentes tareas planificables no está especificado.
Un programa debe comportarse de manera correcta y coherente con todas las secuencias de planificación posibles que sean compatibles con las reglas anteriores.
Construcciones de Synchronization
Construcciones de synchronization
OpenMP especifica varias construcciones de synchronization. Entre ellas:
- critical
- barrier
- taskgroup
- taskwait
- atomic
- flush
La construcción critical
Resumen:
La construcción critical restringe la ejecución del bloque estructurado asociado a un solo hilo a la vez.Sintaxis:
#pragma omp critical [(name)] [[,] hint (hint-expression)] structured-block
Donde hint-expression es una expresión constante entera que evalúa a una pista de sincronización válida.
Cláusulas
hintVinculación
El conjunto de hilos vinculado para una región critical es todos los hilos en el grupo de contención.Semántica
El argumento name se utiliza para identificar la construcción critical. Para cualquier construcción critical en la que no se especifique name, el efecto es como si se hubiera especificado un nombre idéntico (no especificado). La región que corresponde a una construcción critical de un nombre dado se ejecuta como si solo un hilo a la vez, entre todos los hilos en el grupo de contención, ejecutara la región, sin importar a qué equipos pertenecen los hilos.La construcción barrier
Resumen:
La construcción barrier especifica una barrera explícita en el punto donde aparece la construcción. La construcción barrier es una directiva independiente.Sintaxis:
#pragma omp barrier
Vinculación:
El conjunto de hilos vinculado para una región barrier es el equipo actual. Una región barrier se vincula a la región paralela más interna que la envuelve.Semántica:
La construcción barrier especifica una barrera explícita en el punto donde aparece la construcción. A menos que se cancele la región vinculada, todos los hilos del equipo que ejecuta esa región vinculada deben ingresar a la región de barrera y completar la ejecución de todas las tareas explícitas vinculadas a esa región antes de que cualquier hilo continúe la ejecución más allá de la barrera.La región barrier incluye un punto implícito de planificación de tareas en la región de tarea actual.
Sincronizaciones de barrera implícitas
OpenMP especifica sincronizaciones de barrera implícitas como parte del efecto de numerosas construcciones.Algunos ejemplos de sincronizaciones de barrera implícitas son:
- Al final de una región paralela.
- Al final de una región de trabajo compartido, a menos que se especifique una cláusula nowait.
- ...
Con frecuencia, es posible lograr la sincronización necesaria sin tener que especificar sincronizaciones de barrera de manera explícita.
La construcción taskwait
Resumen:
La construcción taskwait especifica una espera en la finalización de las tareas hijas de la tarea actual. La construcción taskwait es una directiva independiente.Sintaxis:
#pragma omp taskwait [clause[[,] clause]…]
Cláusulas:
- depend
- nowait
Vinculación:
La región taskwait se vincula a la región de tarea actual. El conjunto de hilos vinculado para la región taskwait es el equipo actual.Semántica:
Si no se especifica una cláusula depend en la construcción taskwait, la región actual de taskwait se suspende en un punto de planificación de tareas asociado con la construcción. La región de tarea actual permanece suspendida hasta que todas las tareas hijas que generó antes de la región taskwait completen su ejecución.La construcción flush
Resumen:
La construcción flush ejecuta la operación flush de OpenMP. Esta operación hace que la vista temporal de un hilo sobre la memoria sea consistente con la memoria y aplica un orden a las operaciones de memoria de las variables especificadas explícitamente o implícitas. La construcción flush es una directiva independiente.Sintaxis:
#pragma omp flush [memory-order-clause][ (list) ]
Donde memory-order indica los requisitos de orden de memoria para la visibilidad de los efectos de la construcción:
- seq_cst
- acq_rel
- release
- acquire
- relaxed
Vinculación:
El conjunto de hilos vinculado para una región flush es todos los hilos en el conjunto de dispositivos de su operación de flush.Semántica:
La construcción flush ejecuta la operación flush de OpenMP. Esta operación hace que la vista temporal de un hilo sobre la memoria sea consistente con la memoria y establece un orden en las operaciones de memoria de las variables especificadas explícitamente o implícitas. La ejecución de una región flush afecta la memoria y la vista temporal de memoria del hilo que encuentra la construcción. No afecta la vista temporal de otros hilos. Los otros hilos en dispositivos dentro del conjunto de dispositivos deben ejecutar ellos mismos una operación flush para garantizar que vean los efectos de la operación flush del hilo que la encontró.Si no aparece ni una cláusula de memory-order ni un argumento de lista en una construcción flush, el comportamiento es como si la cláusula de memory-order fuera seq_cst.
Una construcción flush con la cláusula seq_cst, ejecutada en un hilo dado, opera como si todos los bloques de almacenamiento de datos accesibles al hilo fueran desinfectados por una operación de flush fuerte. Una construcción flush con una lista aplica una operación de flush fuerte a los elementos de la lista, y la operación flush no se completa hasta que se haya completado para todos los elementos de la lista especificada.Multiplicidad de propiedades de la operación flush
Los aspectos que determinan cuándo una operación flush tiene una propiedad strong, release o acquire no son mutuamente exclusivos. Es decir, una operación flush puede tener simultáneamente las siguientes propiedades:
- strong y release
- strong y acquire
- release y acquire
- strong, release y acquire
Operaciones flush implícitas
Numerosas directivas OpenMP implican la ejecución de la operación flush, a veces incluso antes de empezar y al terminar el bloque estructurado sobre el que tienen efecto.
- Algunas directivas que implican la ejecución implícita de la operación flush con la propiedad release son:
barrier
parallel
critical
- Algunas directivas que implican la ejecución implícita de la operación flush con la propiedad acquire son:
barrier
critical
Bajo determinadas circunstancias y para la mayoría de los casos, es posible evitar completamente tener que invocar la operación flush de manera explícita.
De lo contrario, si se especifica una o más cláusulas depend,...