Compartir a través de


3. Funciones de biblioteca en tiempo de ejecución

En esta sección se describen las funciones de biblioteca en tiempo de ejecución de OpenMP C y C++. El encabezado <omp.h> declara dos tipos, varias funciones que se pueden usar para controlar y consultar el entorno de ejecución paralelo y las funciones de bloqueo que se pueden usar para sincronizar el acceso a los datos.

El tipo omp_lock_t es un tipo de objeto capaz de representar que un bloqueo está disponible o que un subproceso posee un bloqueo. Estos bloqueos se conocen como bloqueos simples.

El tipo omp_nest_lock_t es un tipo de objeto capaz de representar que un bloqueo está disponible o la identidad del subproceso que posee el bloqueo y un recuento de anidamiento (descrito a continuación). Estos bloqueos se conocen como bloqueos anidados.

Las funciones de biblioteca son funciones externas con vinculación "C".

Las descripciones de este capítulo se dividen en los temas siguientes:

3.1 Funciones de entorno de ejecución

Las funciones descritas en esta sección afectan y supervisan subprocesos, procesadores y el entorno paralelo:

3.1.1 omp_set_num_threads (función)

La función omp_set_num_threads establece el número predeterminado de subprocesos que se van a usar para regiones paralelas posteriores que no especifican una cláusula num_threads. El formato es el siguiente:

#include <omp.h>
void omp_set_num_threads(int num_threads);

El valor del parámetro num_threads debe ser un entero positivo. Su efecto depende de si se habilita el ajuste dinámico del número de subprocesos. Para obtener un conjunto completo de reglas sobre la interacción entre la función omp_set_num_threads y el ajuste dinámico de subprocesos, consulte la sección 2.3.

Esta función tiene los efectos descritos anteriormente cuando se llama desde una parte del programa donde la función omp_in_parallel devuelve cero. Si se llama desde una parte del programa donde la función omp_in_parallel devuelve un valor distinto de cero, el comportamiento de esta función no está definido.

Esta llamada tiene prioridad sobre la variable de entorno OMP_NUM_THREADS. El valor predeterminado para el número de subprocesos, que se pueden establecer llamando a omp_set_num_threads o estableciendo la variable de entorno OMP_NUM_THREADS, se puede invalidar explícitamente en una sola directiva parallel especificando la cláusula num_threads.

Para obtener más información, vea omp_set_dynamic.

Referencias cruzadas

3.1.2 omp_get_num_threads (función)

La función omp_get_num_threads devuelve el número de subprocesos actualmente en el equipo que ejecuta la región paralela desde la que se llama. El formato es el siguiente:

#include <omp.h>
int omp_get_num_threads(void);

La cláusula num_threads, la función omp_set_num_threads y la variable de entorno OMP_NUM_THREADS controlan el número de subprocesos de un equipo.

Si el usuario no ha establecido explícitamente el número de subprocesos, el valor predeterminado es definido por la implementación. Esta función se enlaza a la directiva envolvente parallel más cercana. Si se llama desde una parte serie de un programa o desde una región paralela anidada que se serializa, esta función devuelve 1.

Para obtener más información, vea omp_set_dynamic.

Referencias cruzadas

3.1.3 omp_get_max_threads (función)

La función omp_get_max_threads devuelve un entero que se garantiza que sea al menos tan grande como el número de subprocesos que se usarían para formar un equipo si se hubiera visto una región paralela sin una cláusula num_threads en ese punto del código. El formato es el siguiente:

#include <omp.h>
int omp_get_max_threads(void);

A continuación se expresa un límite inferior en el valor de omp_get_max_threads:

threads-used-for-next-team<= omp_get_max_threads

Tenga en cuenta que si otra región paralela usa la cláusula num_threads para solicitar un número específico de subprocesos, la garantía en el límite inferior del resultado de omp_get_max_threads ya no contiene.

El valor omp_get_max_threads devuelto de la función se puede usar para asignar dinámicamente suficiente almacenamiento para todos los subprocesos del equipo formados en la siguiente región paralela.

Referencias cruzadas

3.1.4 omp_get_thread_num (función)

La función omp_get_thread_num devuelve el número de subproceso, dentro de su equipo, del subproceso que ejecuta la función. El número de subproceso está comprendido entre 0 y omp_get_num_threads()-1, ambos incluidos. El subproceso maestro del equipo es el subproceso 0.

El formato es el siguiente:

#include <omp.h>
int omp_get_thread_num(void);

Si se llama desde una región de serie, omp_get_thread_num devuelve 0. Si se llama desde dentro de una región paralela anidada que se serializa, esta función devuelve 0.

Referencias cruzadas

3.1.5 omp_get_num_procs (función)

La función omp_get_num_procs devuelve el número de procesadores que están disponibles para el programa en el momento en que se llama a la función. El formato es el siguiente:

#include <omp.h>
int omp_get_num_procs(void);

3.1.6 omp_in_parallel (función)

La función omp_in_parallel devuelve un valor distinto de cero si se llama dentro de la extensión dinámica de una región paralela que se ejecuta en paralelo; de lo contrario, devuelve 0. El formato es el siguiente:

#include <omp.h>
int omp_in_parallel(void);

Esta función devuelve un valor distinto de cero cuando se llama desde dentro de una región que se ejecuta en paralelo, incluidas las regiones anidadas que se serializan.

3.1.7 omp_set_dynamic (función)

La función omp_set_dynamic habilita o deshabilita el ajuste dinámico del número de subprocesos disponibles para la ejecución de regiones paralelas. El formato es el siguiente:

#include <omp.h>
void omp_set_dynamic(int dynamic_threads);

Si dynamic_threads se evalúa como un valor distinto de cero, el número de subprocesos que se usan para ejecutar próximas regiones paralelas se puede ajustar automáticamente mediante el entorno en tiempo de ejecución para usar mejor los recursos del sistema. Como consecuencia, el número de subprocesos especificados por el usuario es el número máximo de subprocesos. El número de subprocesos del equipo que ejecuta una región paralela permanece fijo durante la duración de esa región paralela y la función notifica omp_get_num_threads.

Si dynamic_threads se evalúa como 0, se deshabilita el ajuste dinámico.

Esta función tiene los efectos descritos anteriormente cuando se llama desde una parte del programa donde la función omp_in_parallel devuelve cero. Si se llama desde una parte del programa donde la función omp_in_parallel devuelve un valor distinto de cero, el comportamiento de esta función no está definido.

La llamada a omp_set_dynamic tiene prioridad sobre la variable de entorno OMP_DYNAMIC.

El valor predeterminado para el ajuste dinámico de subprocesos está definido por la implementación. Como resultado, los códigos de usuario que dependen de un número específico de subprocesos para la ejecución correcta deben deshabilitar explícitamente los subprocesos dinámicos. Las implementaciones no son necesarias para proporcionar la capacidad de ajustar dinámicamente el número de subprocesos, pero son necesarios para proporcionar la interfaz para admitir la portabilidad en todas las plataformas.

Específico de Microsoft

La compatibilidad actual de omp_get_dynamic y omp_set_dynamic es la siguiente:

El parámetro de entrada para no afecta a omp_set_dynamic la directiva de subprocesos y no cambia el número de subprocesos. omp_get_num_threads siempre devuelve el número definido por el usuario, si se establece o el número de subproceso predeterminado. En la implementación actual de Microsoft, omp_set_dynamic(0) desactiva el subproceso dinámico para que el conjunto existente de subprocesos se pueda reutilizar para la siguiente región paralela. omp_set_dynamic(1) activa el subproceso dinámico descartando el conjunto existente de subprocesos y creando un nuevo conjunto para la próxima región paralela. El número de subprocesos del nuevo conjunto es el mismo que el conjunto anterior y se basa en el valor devuelto de omp_get_num_threads. Por lo tanto, para obtener el mejor rendimiento, use omp_set_dynamic(0) para reutilizar los subprocesos existentes.

Referencias cruzadas

3.1.8 omp_get_dynamic (función)

La función omp_get_dynamic devuelve un valor distinto de cero si el ajuste dinámico de subprocesos está habilitado; de lo contrario devuelve 0. El formato es el siguiente:

#include <omp.h>
int omp_get_dynamic(void);

Si la implementación no implementa el ajuste dinámico del número de subprocesos, esta función siempre devuelve 0. Para obtener más información, vea omp_set_dynamic.

Referencias cruzadas

  • Para obtener una descripción del ajuste dinámico de subprocesos, consulte omp_set_dynamic.

3.1.9 omp_set_nested (función)

La función omp_set_nested habilita o deshabilita el paralelismo anidado. El formato es el siguiente:

#include <omp.h>
void omp_set_nested(int nested);

Si se evalúa como 0, el paralelismo anidado está deshabilitado, que es el valor predeterminado, y las regiones paralelas anidadas se serializan y ejecutan mediante el subproceso actual. De lo contrario, el paralelismo anidado está habilitado y las regiones paralelas anidadas pueden implementar subprocesos adicionales para formar equipos anidados.

Esta función tiene los efectos descritos anteriormente cuando se llama desde una parte del programa donde la función omp_in_parallel devuelve cero. Si se llama desde una parte del programa donde la función omp_in_parallel devuelve un valor distinto de cero, el comportamiento de esta función no está definido.

Esta llamada tiene prioridad sobre la variable de entorno OMP_NESTED.

Cuando se habilita el paralelismo anidado, el número de subprocesos usados para ejecutar regiones paralelas anidadas está definida por la implementación. Como resultado, las implementaciones compatibles con OpenMP pueden serializar regiones paralelas anidadas incluso cuando se habilita el paralelismo anidado.

Referencias cruzadas

3.1.10 omp_get_nested (función)

La función omp_get_nested devuelve un valor distinto de cero si el paralelismo anidado está habilitado, y 0 si está deshabilitado. Para más información sobre paralelismos anidados, consulte omp_set_nested. El formato es el siguiente:

#include <omp.h>
int omp_get_nested(void);

Si una implementación no implementa paralelismo anidado, esta función siempre devuelve 0.

3.2 Funciones de bloqueo

Las funciones descritas en esta sección manipulan los bloqueos usados para la sincronización.

Para las siguientes funciones, la variable de bloqueo debe tener el tipo omp_lock_t. Solo se debe tener acceso a esta variable a través de estas funciones. Todas las funciones de bloqueo requieren un argumento que tiene un puntero al tipo omp_lock_t.

Para las siguientes funciones, la variable de bloqueo debe tener el tipo omp_nest_lock_t. Solo se debe tener acceso a esta variable a través de estas funciones. Todas las funciones de bloqueo anidado requieren un argumento que tiene un puntero al tipo omp_nest_lock_t.

Las funciones de bloqueo openMP acceden a la variable de bloqueo de tal forma que siempre leen y actualizan el valor más actual de la variable de bloqueo. Por lo tanto, no es necesario que un programa OpenMP incluya directivas flush explícitas para asegurarse de que el valor de la variable de bloqueo sea coherente entre diferentes subprocesos. (Puede que sea necesario que las directivas flush hagan coherentes los valores de otras variables).

3.2.1 omp_init_lock and omp_init_nest_lock (funciones)

Estas funciones proporcionan los únicos medios para inicializar un bloqueo. Cada función inicializa el bloqueo asociado al parámetro bloqueo para su uso en próximas llamadas. El formato es el siguiente:

#include <omp.h>
void omp_init_lock(omp_lock_t *lock);
void omp_init_nest_lock(omp_nest_lock_t *lock);

El estado inicial se desbloquea (es decir, ningún subproceso posee el bloqueo). Para un bloqueo anidado, el recuento de anidamiento inicial es cero. No es compatible llamar a cualquiera de estas rutinas con una variable de bloqueo que ya se ha inicializado.

3.2.2 omp_destroy_lock and omp_destroy_nest_lock (funciones)

Estas funciones se aseguran de que el bloqueo de variable de bloqueo apuntado no está inicializado. El formato es el siguiente:

#include <omp.h>
void omp_destroy_lock(omp_lock_t *lock);
void omp_destroy_nest_lock(omp_nest_lock_t *lock);

No es compatible llamar a cualquiera de estas rutinas con una variable de bloqueo que no esté inicializada o que no esté bloqueada.

3.2.3 omp_set_lock and omp_set_nest_lock (funciones)

Cada una de estas funciones bloquea el subproceso que ejecuta la función hasta que el bloqueo especificado está disponible y, a continuación, establece el bloqueo. Un bloqueo simple está disponible si está desbloqueado. Un bloqueo anidado está disponible si está desbloqueado o si ya es propiedad del subproceso que ejecuta la función. El formato es el siguiente:

#include <omp.h>
void omp_set_lock(omp_lock_t *lock);
void omp_set_nest_lock(omp_nest_lock_t *lock);

Para un bloqueo simple, el argumento de la función omp_set_lock debe apuntar a una variable de bloqueo inicializada. La propiedad del bloqueo se concede al subproceso que ejecuta la función.

Para un bloqueo anidado, el argumento de la función omp_set_nest_lock debe apuntar a una variable de bloqueo inicializada. El recuento de anidamiento se incrementa y se concede o mantiene la propiedad del bloqueo.

3.2.4 omp_unset_lock and omp_unset_nest_lock (funciones)

Estas funciones proporcionan los medios para liberar la propiedad de un bloqueo. El formato es el siguiente:

#include <omp.h>
void omp_unset_lock(omp_lock_t *lock);
void omp_unset_nest_lock(omp_nest_lock_t *lock);

El argumento de cada una de estas funciones debe apuntar a una variable de bloqueo inicializada propiedad del subproceso que ejecuta la función. Si el subproceso no posee dicho bloqueo, el comportamiento no está definido.

Para un bloqueo simple, la función omp_unset_lock libera el subproceso que ejecuta la función de la propiedad del bloqueo.

Para un bloqueo anidado, la función omp_unset_nest_lock disminuye el recuento de anidamiento y libera el subproceso que ejecuta la función de la propiedad del bloqueo si el recuento resultante es cero.

3.2.5 omp_test_lock and omp_test_nest_lock (funciones)

Estas funciones intentan establecer un bloqueo, pero no bloquean la ejecución del subproceso. El formato es el siguiente:

#include <omp.h>
int omp_test_lock(omp_lock_t *lock);
int omp_test_nest_lock(omp_nest_lock_t *lock);

El argumento debe apuntar a una variable de bloqueo inicializada. Estas funciones intentan establecer un bloqueo de la misma manera que omp_set_lock y omp_set_nest_lock, salvo que no bloquean la ejecución del subproceso.

Para un bloqueo simple, la función omp_test_lock devuelve un valor distinto de cero si el bloqueo se establece correctamente; de lo contrario, devuelve cero.

Para un bloqueo anidado, la función omp_test_nest_lock devuelve el nuevo recuento de anidamiento si el bloqueo se ha establecido correctamente; de lo contrario, devuelve cero.

3.3 Rutinas temporales

Las funciones descritas en esta sección admiten un temporizador portátil de reloj:

  • La función omp_get_wtime devuelve el tiempo de reloj transcurrido.
  • La función omp_get_wtick devuelve segundos entre los tics de reloj sucesivos.

3.3.1 omp_get_wtime (función)

La función omp_get_wtime devuelve un valor de punto flotante de precisión doble igual al tiempo de reloj transcurrido en segundos desde el pasado. El "tiempo real en el pasado" es arbitrario, pero se garantiza que no cambie durante la ejecución del programa de aplicación. El formato es el siguiente:

#include <omp.h>
double omp_get_wtime(void);

Se prevé que la función se usará para medir los tiempos transcurridos, como se muestra en el ejemplo siguiente:

double start;
double end;
start = omp_get_wtime();
... work to be timed ...
end = omp_get_wtime();
printf_s("Work took %f sec. time.\n", end-start);

Los tiempos devueltos son "tiempos por subproceso", lo que significa que no son necesarios para ser coherentes globalmente en todos los subprocesos que participan en una aplicación.

3.3.2 omp_get_wtick (función)

La función omp_get_wtick devuelve un valor de punto flotante de precisión doble igual al número de segundos entre los tics de reloj sucesivos. El formato es el siguiente:

#include <omp.h>
double omp_get_wtick(void);