Cláusulas de OpenMP
Proporciona vínculos a cláusulas usadas en la API de OpenMP.
Visual C++ admite las siguientes cláusulas de OpenMP.
Para atributos generales:
Cláusula | Descripción |
---|---|
if | Especifica si se debe ejecutar un bucle en paralelo o en serie. |
num_threads | Establece el número de subprocesos de un equipo de subprocesos. |
ordenado | Obligatorio en una instrucción for paralela si se va a usar una directiva ordenada en el bucle. |
schedule | Se aplica a la directiva for. |
nowait | Invalida la barrera implícita en una directiva. |
Para los atributos de uso compartido de datos:
Cláusula | Descripción |
---|---|
private | Especifica que cada subproceso debe tener su propia instancia de una variable. |
firstprivate | Especifica que cada subproceso debe tener su propia instancia de una variable y que la variable se debe inicializar con el valor de la variable, ya que existe antes de la construcción paralela. |
lastprivate | Especifica que la versión del contexto envolvente de la variable se establece igual que la versión privada de cualquier subproceso que ejecute la iteración final (construcción de bucle for) o la última sección (#pragma sections). |
shared | Especifica que una o varias variables deben compartirse entre todos los subprocesos. |
default | Especifica el comportamiento de variables sin ámbito en una región paralela. |
reduction | Especifica que una o varias variables que son privadas para cada subproceso son objeto de una operación de reducción al final de la región paralela. |
copyin | Permite que los subprocesos accedan al valor del subproceso principal para una variable threadprivate. |
copyprivate | Especifica que una o varias variables deben compartirse entre todos los subprocesos. |
copyin
Permite que los subprocesos accedan al valor del subproceso principal para una variable threadprivate.
copyin(var)
Parámetros
var
Variable threadprivate
que se inicializará con el valor de la variable en el subproceso principal, tal como existe antes de la construcción paralela.
Comentarios
copyin
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.7 copyin.
Ejemplo
Consulte threadprivate para ver un ejemplo de uso de copyin
.
copyprivate
Especifica que una o varias variables deben compartirse entre todos los subprocesos.
copyprivate(var)
Parámetros
var
Una o varias variables que se van a compartir. Si se especifica más de una variable, separe los nombres de variable con una coma.
Comentarios
copyprivate
se aplica a la directiva single.
Para más información, consulte 2.7.2.8 copyprivate.
Ejemplo
// omp_copyprivate.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>
float x, y, fGlobal = 1.0;
#pragma omp threadprivate(x, y)
float get_float() {
fGlobal += 0.001;
return fGlobal;
}
void use_float(float f, int t) {
printf_s("Value = %f, thread = %d\n", f, t);
}
void CopyPrivate(float a, float b) {
#pragma omp single copyprivate(a, b, x, y)
{
a = get_float();
b = get_float();
x = get_float();
y = get_float();
}
use_float(a, omp_get_thread_num());
use_float(b, omp_get_thread_num());
use_float(x, omp_get_thread_num());
use_float(y, omp_get_thread_num());
}
int main() {
float a = 9.99, b = 123.456;
printf_s("call CopyPrivate from a single thread\n");
CopyPrivate(9.99, 123.456);
printf_s("call CopyPrivate from a parallel region\n");
#pragma omp parallel
{
CopyPrivate(a, b);
}
}
call CopyPrivate from a single thread
Value = 1.001000, thread = 0
Value = 1.002000, thread = 0
Value = 1.003000, thread = 0
Value = 1.004000, thread = 0
call CopyPrivate from a parallel region
Value = 1.005000, thread = 0
Value = 1.005000, thread = 1
Value = 1.006000, thread = 0
Value = 1.006000, thread = 1
Value = 1.007000, thread = 0
Value = 1.007000, thread = 1
Value = 1.008000, thread = 0
Value = 1.008000, thread = 1
default
Especifica el comportamiento de variables sin ámbito en una región paralela.
default(shared | none)
Comentarios
shared
, que está en vigor si la cláusula default
no está especificada, significa que cualquier variable de una región paralela se tratará como si se especificara con la cláusula shared. none
significa que las variables usadas en una región paralela que no tienen ámbito con la cláusula private, shared, reduction, firstprivate o lastprivate provocarán un error del compilador.
default
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.5 default.
Ejemplo
Consulte private para ver un ejemplo de uso de default
.
firstprivate
Especifica que cada subproceso debe tener su propia instancia de una variable y que la variable se debe inicializar con el valor de la variable, ya que existe antes de la construcción paralela.
firstprivate(var)
Parámetros
var
Variable que tendrá instancias en cada subproceso y que se inicializará con el valor de la variable, ya que existe antes de la construcción paralela. Si se especifica más de una variable, separe los nombres de variable con una coma.
Comentarios
firstprivate
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.2 firstprivate.
Ejemplo
Para ver un ejemplo de uso de firstprivate
, consulte el ejemplo en private.
if (OpenMP)
Especifica si se debe ejecutar un bucle en paralelo o en serie.
if(expression)
Parámetros
expression
Expresión integral que, si se evalúa como true (distinto de cero), hace que el código de la región paralela se ejecute en paralelo. Si la expresión se evalúa como false (cero), la región paralela se ejecuta en serie (por un único subproceso).
Comentarios
if
se aplica a las siguientes directivas:
Para obtener más información, consulte 2.3 parallel construct.
Ejemplo
// omp_if.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>
void test(int val)
{
#pragma omp parallel if (val)
if (omp_in_parallel())
{
#pragma omp single
printf_s("val = %d, parallelized with %d threads\n",
val, omp_get_num_threads());
}
else
{
printf_s("val = %d, serialized\n", val);
}
}
int main( )
{
omp_set_num_threads(2);
test(0);
test(2);
}
val = 0, serialized
val = 2, parallelized with 2 threads
lastprivate
Especifica que la versión del contexto envolvente de la variable se establece igual que la versión privada de cualquier subproceso que ejecute la iteración final (construcción de bucle for) o la última sección (#pragma sections).
lastprivate(var)
Parámetros
var
Variable que se establece igual a la versión privada de cualquier subproceso que ejecute la iteración final (construcción de bucle for) o la última sección (#pragma sections).
Comentarios
lastprivate
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.3 lastprivate.
Ejemplo
Consulte schedule para ver un ejemplo de uso de la cláusula lastprivate
.
nowait
Invalida la barrera implícita en una directiva.
nowait
Comentarios
nowait
se aplica a las siguientes directivas:
Para más información, consulte Construcción 2.4.1 for, Construcción 2.4.2 sections y Construcción 2.4.3 single.
Ejemplo
// omp_nowait.cpp
// compile with: /openmp /c
#include <stdio.h>
#define SIZE 5
void test(int *a, int *b, int *c, int size)
{
int i;
#pragma omp parallel
{
#pragma omp for nowait
for (i = 0; i < size; i++)
b[i] = a[i] * a[i];
#pragma omp for nowait
for (i = 0; i < size; i++)
c[i] = a[i]/2;
}
}
int main( )
{
int a[SIZE], b[SIZE], c[SIZE];
int i;
for (i=0; i<SIZE; i++)
a[i] = i;
test(a,b,c, SIZE);
for (i=0; i<SIZE; i++)
printf_s("%d, %d, %d\n", a[i], b[i], c[i]);
}
0, 0, 0
1, 1, 0
2, 4, 1
3, 9, 1
4, 16, 2
num_threads
Establece el número de subprocesos de un equipo de subprocesos.
num_threads(num)
Parámetros
num
Número de subprocesos
Comentarios
La cláusula num_threads
tiene la misma funcionalidad que la función omp_set_num_threads.
num_threads
se aplica a las siguientes directivas:
Para obtener más información, consulte 2.3 parallel construct.
Ejemplo
Consulte parallel para ver un ejemplo de uso de la cláusula num_threads
.
ordered
Obligatorio en una instrucción for paralela si se va a usar una directiva ordenada en el bucle.
ordered
Comentarios
ordered
se aplica a la directiva for.
Para obtener más información, vea 2.4.1 for construct.
Ejemplo
Consulte ordered para ver un ejemplo de uso de la cláusula ordered
.
private
Especifica que cada subproceso debe tener su propia instancia de una variable.
private(var)
Parámetros
var
Variable que tendrá instancias en cada subproceso.
Comentarios
private
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.1 private.
Ejemplo
// openmp_private.c
// compile with: /openmp
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <omp.h>
#define NUM_THREADS 4
#define SLEEP_THREAD 1
#define NUM_LOOPS 2
enum Types {
ThreadPrivate,
Private,
FirstPrivate,
LastPrivate,
Shared,
MAX_TYPES
};
int nSave[NUM_THREADS][MAX_TYPES][NUM_LOOPS] = {{0}};
int nThreadPrivate;
#pragma omp threadprivate(nThreadPrivate)
#pragma warning(disable:4700)
int main() {
int nPrivate = NUM_THREADS;
int nFirstPrivate = NUM_THREADS;
int nLastPrivate = NUM_THREADS;
int nShared = NUM_THREADS;
int nRet = 0;
int i;
int j;
int nLoop = 0;
nThreadPrivate = NUM_THREADS;
printf_s("These are the variables before entry "
"into the parallel region.\n");
printf_s("nThreadPrivate = %d\n", nThreadPrivate);
printf_s(" nPrivate = %d\n", nPrivate);
printf_s(" nFirstPrivate = %d\n", nFirstPrivate);
printf_s(" nLastPrivate = %d\n", nLastPrivate);
printf_s(" nShared = %d\n\n", nShared);
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel copyin(nThreadPrivate) private(nPrivate) shared(nShared) firstprivate(nFirstPrivate)
{
#pragma omp for schedule(static) lastprivate(nLastPrivate)
for (i = 0 ; i < NUM_THREADS ; ++i) {
for (j = 0 ; j < NUM_LOOPS ; ++j) {
int nThread = omp_get_thread_num();
assert(nThread < NUM_THREADS);
if (nThread == SLEEP_THREAD)
Sleep(100);
nSave[nThread][ThreadPrivate][j] = nThreadPrivate;
nSave[nThread][Private][j] = nPrivate;
nSave[nThread][Shared][j] = nShared;
nSave[nThread][FirstPrivate][j] = nFirstPrivate;
nSave[nThread][LastPrivate][j] = nLastPrivate;
nThreadPrivate = nThread;
nPrivate = nThread;
nShared = nThread;
nLastPrivate = nThread;
--nFirstPrivate;
}
}
}
for (i = 0 ; i < NUM_LOOPS ; ++i) {
for (j = 0 ; j < NUM_THREADS ; ++j) {
printf_s("These are the variables at entry of "
"loop %d of thread %d.\n", i + 1, j);
printf_s("nThreadPrivate = %d\n",
nSave[j][ThreadPrivate][i]);
printf_s(" nPrivate = %d\n",
nSave[j][Private][i]);
printf_s(" nFirstPrivate = %d\n",
nSave[j][FirstPrivate][i]);
printf_s(" nLastPrivate = %d\n",
nSave[j][LastPrivate][i]);
printf_s(" nShared = %d\n\n",
nSave[j][Shared][i]);
}
}
printf_s("These are the variables after exit from "
"the parallel region.\n");
printf_s("nThreadPrivate = %d (The last value in the "
"main thread)\n", nThreadPrivate);
printf_s(" nPrivate = %d (The value prior to "
"entering parallel region)\n", nPrivate);
printf_s(" nFirstPrivate = %d (The value prior to "
"entering parallel region)\n", nFirstPrivate);
printf_s(" nLastPrivate = %d (The value from the "
"last iteration of the loop)\n", nLastPrivate);
printf_s(" nShared = %d (The value assigned, "
"from the delayed thread, %d)\n\n",
nShared, SLEEP_THREAD);
}
These are the variables before entry into the parallel region.
nThreadPrivate = 4
nPrivate = 4
nFirstPrivate = 4
nLastPrivate = 4
nShared = 4
These are the variables at entry of loop 1 of thread 0.
nThreadPrivate = 4
nPrivate = 1310720
nFirstPrivate = 4
nLastPrivate = 1245104
nShared = 3
These are the variables at entry of loop 1 of thread 1.
nThreadPrivate = 4
nPrivate = 4488
nFirstPrivate = 4
nLastPrivate = 19748
nShared = 0
These are the variables at entry of loop 1 of thread 2.
nThreadPrivate = 4
nPrivate = -132514848
nFirstPrivate = 4
nLastPrivate = -513199792
nShared = 4
These are the variables at entry of loop 1 of thread 3.
nThreadPrivate = 4
nPrivate = 1206
nFirstPrivate = 4
nLastPrivate = 1204
nShared = 2
These are the variables at entry of loop 2 of thread 0.
nThreadPrivate = 0
nPrivate = 0
nFirstPrivate = 3
nLastPrivate = 0
nShared = 0
These are the variables at entry of loop 2 of thread 1.
nThreadPrivate = 1
nPrivate = 1
nFirstPrivate = 3
nLastPrivate = 1
nShared = 1
These are the variables at entry of loop 2 of thread 2.
nThreadPrivate = 2
nPrivate = 2
nFirstPrivate = 3
nLastPrivate = 2
nShared = 2
These are the variables at entry of loop 2 of thread 3.
nThreadPrivate = 3
nPrivate = 3
nFirstPrivate = 3
nLastPrivate = 3
nShared = 3
These are the variables after exit from the parallel region.
nThreadPrivate = 0 (The last value in the main thread)
nPrivate = 4 (The value prior to entering parallel region)
nFirstPrivate = 4 (The value prior to entering parallel region)
nLastPrivate = 3 (The value from the last iteration of the loop)
nShared = 1 (The value assigned, from the delayed thread, 1)
reduction
Especifica que una o varias variables que son privadas para cada subproceso son objeto de una operación de reducción al final de la región paralela.
reduction(operation:var)
Parámetros
operación
Operador de la operación que se va a realizar en las variables var al final de la región paralela.
var
Una o varias variables en las que se va a realizar la reducción escalar. Si se especifica más de una variable, separe los nombres de variable con una coma.
Comentarios
reduction
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.6 reduction.
Ejemplo
// omp_reduction.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>
#define NUM_THREADS 4
#define SUM_START 1
#define SUM_END 10
#define FUNC_RETS {1, 1, 1, 1, 1}
int bRets[5] = FUNC_RETS;
int nSumCalc = ((SUM_START + SUM_END) * (SUM_END - SUM_START + 1)) / 2;
int func1( ) {return bRets[0];}
int func2( ) {return bRets[1];}
int func3( ) {return bRets[2];}
int func4( ) {return bRets[3];}
int func5( ) {return bRets[4];}
int main( )
{
int nRet = 0,
nCount = 0,
nSum = 0,
i,
bSucceed = 1;
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel reduction(+ : nCount)
{
nCount += 1;
#pragma omp for reduction(+ : nSum)
for (i = SUM_START ; i <= SUM_END ; ++i)
nSum += i;
#pragma omp sections reduction(&& : bSucceed)
{
#pragma omp section
{
bSucceed = bSucceed && func1( );
}
#pragma omp section
{
bSucceed = bSucceed && func2( );
}
#pragma omp section
{
bSucceed = bSucceed && func3( );
}
#pragma omp section
{
bSucceed = bSucceed && func4( );
}
#pragma omp section
{
bSucceed = bSucceed && func5( );
}
}
}
printf_s("The parallel section was executed %d times "
"in parallel.\n", nCount);
printf_s("The sum of the consecutive integers from "
"%d to %d, is %d\n", 1, 10, nSum);
if (bSucceed)
printf_s("All of the functions, func1 through "
"func5 succeeded!\n");
else
printf_s("One or more of the functions, func1 "
"through func5 failed!\n");
if (nCount != NUM_THREADS)
{
printf_s("ERROR: For %d threads, %d were counted!\n",
NUM_THREADS, nCount);
nRet |= 0x1;
}
if (nSum != nSumCalc)
{
printf_s("ERROR: The sum of %d through %d should be %d, "
"but %d was reported!\n",
SUM_START, SUM_END, nSumCalc, nSum);
nRet |= 0x10;
}
if (bSucceed != (bRets[0] && bRets[1] &&
bRets[2] && bRets[3] && bRets[4]))
{
printf_s("ERROR: The sum of %d through %d should be %d, "
"but %d was reported!\n",
SUM_START, SUM_END, nSumCalc, nSum);
nRet |= 0x100;
}
}
The parallel section was executed 4 times in parallel.
The sum of the consecutive integers from 1 to 10, is 55
All of the functions, func1 through func5 succeeded!
schedule
Se aplica a la directiva for.
schedule(type[,size])
Parámetros
type
El tipo de programación, dynamic
, guided
, runtime
, o static
.
size
(Opcional) Especifica el tamaño de las iteraciones. size debe ser un entero. No es válido cuando type es runtime
.
Comentarios
Para obtener más información, vea 2.4.1 for construct.
Ejemplo
// omp_schedule.cpp
// compile with: /openmp
#include <windows.h>
#include <stdio.h>
#include <omp.h>
#define NUM_THREADS 4
#define STATIC_CHUNK 5
#define DYNAMIC_CHUNK 5
#define NUM_LOOPS 20
#define SLEEP_EVERY_N 3
int main( )
{
int nStatic1[NUM_LOOPS],
nStaticN[NUM_LOOPS];
int nDynamic1[NUM_LOOPS],
nDynamicN[NUM_LOOPS];
int nGuided[NUM_LOOPS];
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel
{
#pragma omp for schedule(static, 1)
for (int i = 0 ; i < NUM_LOOPS ; ++i)
{
if ((i % SLEEP_EVERY_N) == 0)
Sleep(0);
nStatic1[i] = omp_get_thread_num( );
}
#pragma omp for schedule(static, STATIC_CHUNK)
for (int i = 0 ; i < NUM_LOOPS ; ++i)
{
if ((i % SLEEP_EVERY_N) == 0)
Sleep(0);
nStaticN[i] = omp_get_thread_num( );
}
#pragma omp for schedule(dynamic, 1)
for (int i = 0 ; i < NUM_LOOPS ; ++i)
{
if ((i % SLEEP_EVERY_N) == 0)
Sleep(0);
nDynamic1[i] = omp_get_thread_num( );
}
#pragma omp for schedule(dynamic, DYNAMIC_CHUNK)
for (int i = 0 ; i < NUM_LOOPS ; ++i)
{
if ((i % SLEEP_EVERY_N) == 0)
Sleep(0);
nDynamicN[i] = omp_get_thread_num( );
}
#pragma omp for schedule(guided)
for (int i = 0 ; i < NUM_LOOPS ; ++i)
{
if ((i % SLEEP_EVERY_N) == 0)
Sleep(0);
nGuided[i] = omp_get_thread_num( );
}
}
printf_s("------------------------------------------------\n");
printf_s("| static | static | dynamic | dynamic | guided |\n");
printf_s("| 1 | %d | 1 | %d | |\n",
STATIC_CHUNK, DYNAMIC_CHUNK);
printf_s("------------------------------------------------\n");
for (int i=0; i<NUM_LOOPS; ++i)
{
printf_s("| %d | %d | %d | %d |"
" %d |\n",
nStatic1[i], nStaticN[i],
nDynamic1[i], nDynamicN[i], nGuided[i]);
}
printf_s("------------------------------------------------\n");
}
------------------------------------------------
| static | static | dynamic | dynamic | guided |
| 1 | 5 | 1 | 5 | |
------------------------------------------------
| 0 | 0 | 0 | 2 | 1 |
| 1 | 0 | 3 | 2 | 1 |
| 2 | 0 | 3 | 2 | 1 |
| 3 | 0 | 3 | 2 | 1 |
| 0 | 0 | 2 | 2 | 1 |
| 1 | 1 | 2 | 3 | 3 |
| 2 | 1 | 2 | 3 | 3 |
| 3 | 1 | 0 | 3 | 3 |
| 0 | 1 | 0 | 3 | 3 |
| 1 | 1 | 0 | 3 | 2 |
| 2 | 2 | 1 | 0 | 2 |
| 3 | 2 | 1 | 0 | 2 |
| 0 | 2 | 1 | 0 | 3 |
| 1 | 2 | 2 | 0 | 3 |
| 2 | 2 | 2 | 0 | 0 |
| 3 | 3 | 2 | 1 | 0 |
| 0 | 3 | 3 | 1 | 1 |
| 1 | 3 | 3 | 1 | 1 |
| 2 | 3 | 3 | 1 | 1 |
| 3 | 3 | 0 | 1 | 3 |
------------------------------------------------
compartido
Especifica que una o varias variables deben compartirse entre todos los subprocesos.
shared(var)
Parámetros
var
Una o varias variables que se van a compartir. Si se especifica más de una variable, separe los nombres de variable con una coma.
Comentarios
Otra manera de compartir variables entre subprocesos es con la cláusula copyprivate.
shared
se aplica a las siguientes directivas:
Para más información, consulte 2.7.2.4 shared.
Ejemplo
Consulte private para ver un ejemplo de uso de shared
.