Compartir vía


1. Introducción

En este documento se especifica una colección de directivas del compilador, funciones de biblioteca y variables de entorno que podrá usar para especificar el paralelismo de memoria compartida en los programas de C y C++. La funcionalidad descrita en este documento se conoce colectivamente como interfaz de programa de aplicaciones (API) de OpenMP C/C++. El objetivo de esta especificación es proporcionar un modelo para la programación en paralelo que permita que un programa sea portátil entre arquitecturas de memoria compartida de diferentes proveedores. Los compiladores de muchos proveedores admiten la API de OpenMP C/C++. Podrá encontrar más información sobre OpenMP, incluyendo la interfaz de programa de aplicaciones de OpenMP Fortran, en el siguiente sitio web:

https://www.openmp.org

Las directivas, las funciones de biblioteca y las variables de entorno definidas en este documento permiten crear y administrar programas paralelos a la vez que permiten la portabilidad. Las directivas amplían el modelo de programación secuencial de C y C++ con construcciones de varios datos de programa único (SPMD), construcciones de uso compartido de trabajo y construcciones de sincronización. También apoyan el uso compartido y la privatización de los datos. Los compiladores que admitan la API de OpenMP C y C++ incluirán una opción de línea de comandos para el compilador que activa y permite interpretar todas las directivas del compilador de OpenMP.

1.1 Ámbito

Esta especificación solo abarca la paralelización dirigida por el usuario, donde se definen explícitamente las acciones que el compilador y el sistema en tiempo de ejecución tomarán para ejecutar el programa en paralelo. Las implementaciones de OpenMP C y C++ no son necesarias para comprobar las dependencias, conflictos, interbloqueos, condiciones de carrera u otros problemas que den lugar a ejecuciones incorrectas del programa. Usted es responsable de asegurarse de que la aplicación que use las construcciones de API de OpenMP C y C++ se ejecute correctamente. Las directivas y la paralización automática generadas por el compilador para ayudar a esta paralelización no se tratarán en este documento.

1.2 Definición de términos

En este documento se emplean los términos siguientes:

  • barrera

    Punto de sincronización al que deberán llegar todos los subprocesos de un equipo. Cada subproceso esperará hasta que lleguen todos los subprocesos del equipo en ese momento. Hay barreras explícitas identificadas por directivas y barreras implícitas creadas por la implementación.

  • construir

    Una construcción es una instrucción. Consiste en una directiva seguida de un bloque estructurado. Algunas directivas no forman parte de una construcción. (Consulte la directiva OpenMP en el apéndice C).

  • directiva

    Un #pragma C o C++ seguido del identificador omp, otro texto y una nueva línea. La directiva especifica el comportamiento del programa.

  • extensión dinámica

    Todas las instrucciones de la extensión léxica, además de cualquier instrucción dentro de una función que se ejecuta como resultado de la ejecución de instrucciones dentro de la extensión léxica. A una extensión dinámica también se la conoce como región.

  • extensión léxica

    Instrucciones que se mantienen léxicamente dentro de un bloque estructurado.

  • subproceso maestro

    Subproceso que crea un equipo cuando se escribe una región paralela.

  • región paralela

    Instrucciones que se enlazan a una construcción paralela de OpenMP y pueden ejecutarse mediante muchos subprocesos.

  • privado

    Una variable privada asigna un nombre a un bloque de almacenamiento que es único para el subproceso que realiza la referencia. Hay varias maneras de especificar que una variable sea privada: una definición dentro de una región paralela, una directiva threadprivate, una cláusula private, firstprivate, lastprivate o reduction, o bien el uso de la variable como una variable de control de bucle for en un bucle for inmediatamente después de una directiva for o parallel for.

  • región

    Una extensión dinámica.

  • región de serie

    Instrucciones ejecutadas solo por el subproceso maestro fuera de la extensión dinámica de cualquier región paralela.

  • serialize

    Para ejecutar una construcción paralela con:

    • un equipo de subprocesos que consta de un único subproceso (que es el subproceso maestro para esa construcción paralela),

    • orden serie de ejecución de las instrucciones dentro del bloque estructurado (el mismo orden que tendría el bloque si no formara parte de una construcción paralela) y

    • no hay ningún efecto en el valor devuelto por omp_in_parallel() (aparte de los efectos de las construcciones paralelas anidadas).

  • shared

    Una variable compartida asigna un nombre a un único bloque de almacenamiento. Todos los subprocesos de un equipo que accedan a esta variable también accederán a este único bloque de almacenamiento.

  • bloque estructurado

    Un bloque estructurado es una instrucción (única o compuesta) que tiene una sola entrada y una única salida. Si hubiera un salto o una salida de una instrucción, esa instrucción será un bloque estructurado. (Esta regla incluye una llamada a longjmp(3C) o el uso de throw, aunque se permitirá una llamada a exit). Si su ejecución comenzara siempre en la apertura { y siempre terminara en el cierre }, una instrucción compuesta será un bloque estructurado. Un bloque try de instrucción de expresión, instrucción de selección o instrucción de iteración será un bloque estructurado si la instrucción compuesta correspondiente obtenida al incluirla en { y } fuera un bloque estructurado. Una instrucción de salto, una instrucción etiquetada o una instrucción de declaración no serán bloques estructurados.

  • equipo

    Uno o varios subprocesos cooperando en la ejecución de una construcción.

  • thread

    Entidad de ejecución que tiene un flujo de control de serie, un conjunto de variables privadas y acceso a variables compartidas.

  • variable

    Identificador, calificado opcionalmente por nombres de espacio de nombres, que asigna un nombre a un objeto.

1.3 Modelo de ejecución

OpenMP usa el modelo de bifurcación o combinación de ejecución en paralelo. Aunque este modelo de bifurcación o combinación pueda ser útil para resolver varios problemas, se adaptará a aplicaciones grandes basadas en matrices. OpenMP está pensado para admitir programas que se ejecuten correctamente como programas paralelos (muchos subprocesos de ejecución y una biblioteca de compatibilidad de OpenMP completa). También será para los programas que se ejecuten correctamente como programas secuenciales (directivas omitidas y una sencilla biblioteca de códigos auxiliares de OpenMP). Sin embargo, es posible y está permitido desarrollar programas que no se comporten correctamente cuando se ejecuten secuencialmente. Además, diferentes grados de paralelismo podrían dar lugar a resultados numéricos diferentes debido a cambios en la asociación de operaciones numéricas. Por ejemplo, una reducción de suma en serie podría tener un patrón diferente de asociaciones de suma que una reducción paralela. Estas diferentes asociaciones podrían cambiar los resultados de las sumas de números de punto flotante.

Un programa escrito con la API de OpenMP C/C++ comenzará la ejecución como un único subproceso de ejecución denominado subproceso maestro. El subproceso maestro se ejecutará en una región de serie hasta que se encuentre la primera construcción paralela. En la API de OpenMP C/C++, la directiva parallel constituye una construcción paralela. Cuando se encuentre una construcción paralela, el subproceso maestro creará un equipo de subprocesos y el maestro se convertirá en maestro del equipo. Cada subproceso del equipo ejecutará las instrucciones en la extensión dinámica de una región paralela, excepto aquellas construcciones que sean de uso compartido de trabajo. Todos los subprocesos del equipo deberán encontrar construcciones de uso compartido de trabajo en el mismo orden y, además, uno o varios de los subprocesos ejecutarán las instrucciones dentro del bloque estructurado asociado. Las barreras implícitas que estén al final de construcciones de uso compartido de trabajo sin una cláusula nowait se ejecutarán por todos los subprocesos del equipo.

Si un subproceso modificara un objeto compartido, afectará no solo a su propio entorno de ejecución, sino también a los de los demás subprocesos del programa. Se garantiza que la modificación se completará, desde el punto de vista de otro subproceso, en el siguiente punto de secuencia (tal y como se define en el lenguaje base) solo si el objeto se declarara como volátil. De lo contrario, se garantizará que la modificación se complete después del primer subproceso de modificación. A continuación, los demás subprocesos (o simultáneamente) verán una directiva flush que especificará el objeto (ya sea implícita o explícitamente). Cuando las directivas flush implícitas por otras directivas de OpenMP no garanticen el orden correcto de los efectos secundarios, será responsabilidad del programador proporcionar directivas flush adicionales y explícitas.

Tras la finalización de la construcción paralela, los subprocesos del equipo se sincronizarán con una barrera implícita y solo el subproceso maestro continuará la ejecución. Cualquier número de construcciones paralelas se puede especificar en un único programa. Como resultado, un programa se podrá bifurcar y combinar muchas veces durante la ejecución.

La API de OpenMP C/C++ permite a los programadores usar directivas en funciones llamadas desde construcciones paralelas. Las directivas que no aparezcan en la extensión léxica de una construcción paralela, pero que puedan estar en la extensión dinámica, se denominan directivas huérfanas. Con directivas huérfanas, los programadores podrán ejecutar partes principales de su programa en paralelo con solo cambios mínimos en el programa secuencial. Con esta funcionalidad, podrá codificar construcciones paralelas en los niveles superiores del árbol de llamadas del programa y usar directivas para controlar la ejecución en cualquiera de las funciones que se llamen.

Las llamadas no asincrónicas a funciones de salida de C y C++ que escriban en el mismo archivo podrán dar lugar a salidas en las que los datos escritos por diferentes subprocesos aparezcan en orden no determinista. De forma similar, las llamadas no asincrónicas a funciones de entrada que lean el mismo archivo podrían leer datos en orden no determinista. El uso sin sincronizar de E/S, de modo que cada subproceso tenga acceso a un archivo diferente, producirá los mismos resultados que la ejecución en serie de las funciones de E/S.

Cumplimiento normativo de la versión 1.4

Una implementación de la API de OpenMP C/C++ será compatible con OpenMP si reconoce y conserva la semántica de todos los elementos de esta especificación, tal y como se establece en los capítulos 1, 2, 3, 4 y el anexo C. Los anexos A, B, D, E y F serán solo para fines informativos y no formarán parte de la especificación. Las implementaciones que incluyan solo un subconjunto de la API no serán compatibles con OpenMP.

La API de OpenMP C y C++ es una extensión del lenguaje base compatible con una implementación. Si el lenguaje base no admitiera una construcción o extensión de lenguaje que apareciera en este documento, la implementación de OpenMP no será necesaria para admitirlo.

Todas las funciones estándar de la biblioteca de C y C++ y las funciones integradas (es decir, las funciones de las que el compilador tiene conocimientos específicos) deberán ser seguras para subprocesos. El uso sin sincronizar de funciones seguras para subprocesos por diferentes subprocesos dentro de una región paralela no producirá un comportamiento indefinido. Sin embargo, es posible que el comportamiento no sea el mismo que en una región de serie. (Una función de generación de números aleatorios es un ejemplo).

La API de OpenMP C/C++ especifica que cierto comportamiento está definido por la implementación. Se requerirá una implementación de OpenMP conforme para definir y documentar su comportamiento en estos casos. Para obtener una lista de los comportamientos definidos por la implementación, consulte el anexo E.

1.5 Referencias normativas

  • ISO/IEC 9899:1999, Tecnología de la información - Lenguajes de programación - C. Esta especificación de API de OpenMP hace referencia a ISO/IEC 9899:1999 como C99.

  • ISO/IEC 9899:1990, Tecnología de la información - Lenguajes de programación - C. Esta especificación de API de OpenMP hace referencia a ISO/IEC 9899:1990 como C90.

  • ISO/IEC 14882:1998, Tecnología de la información - Lenguajes de programación - C++. Esta especificación de API de OpenMP hace referencia a ISO/IEC 14882:1998 como C++.

Allá donde esta especificación de API de OpenMP haga referencia a C, se hará referencia al lenguaje base admitido por la implementación.

1.6 Organización