Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Visual C++ admite actualmente el estándar OpenMP 2.0, pero Visual Studio 2019 también ofrece ahora funcionalidad SIMD.
Nota:
Para usar SIMD, compile con el modificador -openmp:experimental
que habilita características adicionales de OpenMP no disponibles al usar el modificador -openmp
.
El modificador -openmp:experimental
incluye -openmp
, lo que significa que todas las características de OpenMP 2.0 se incluyen en su uso.
Para obtener más información, vea la extensión SIMD para C++ OpenMP en Visual Studio.
OpenMP SIMD en Visual C++
OpenMP SIMD, introducido en el estándar OpenMP 4.0, tiene como destino la creación de bucles que admiten vectores. Mediante el uso de la simd
directiva antes de un bucle, el compilador puede omitir las dependencias vectoriales, hacer que el bucle sea lo más descriptivo posible y respetar la intención de los usuarios de tener varias iteraciones de bucle ejecutadas simultáneamente.
#pragma omp simd
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
Visual C++ proporciona pragmas de bucle no OpenMP similares como #pragma vector
y #pragma ivdep
, sin embargo, con OpenMP SIMD, el compilador puede hacer más, como:
- Siempre se permite omitir las dependencias de vector presentes.
-
/fp:fast
está habilitado dentro del bucle. - Los bucles externos y los bucles con llamadas de función son compatibles con vectores.
- Los bucles anidados se pueden fusionar en un bucle y ser compatibles con vectores.
- Aceleración híbrida con
#pragma omp for simd
para habilitar el subproceso múltiple general y los vectores específicos.
En el caso de los bucles compatibles con vectores, el compilador permanece en silencio a menos que use un modificador de registro de compatibilidad vectorial:
cl -O2 -openmp:experimental -Qvec-report:2 mycode.cpp
mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200'
mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200'
mycode.cpp(96) : info C5001: Omp simd loop vectorized
En el caso de bucles no aptos para vectores, el compilador emite un mensaje para cada uno:
cl -O2 -openmp:experimental mycode.cpp
mycode.cpp(84) : info C5002: Omp simd loop not vectorized due to reason '1200'
mycode.cpp(90) : info C5002: Omp simd loop not vectorized due to reason '1200'
Cláusulas
La directiva OpenMP SIMD también puede tomar las siguientes cláusulas para mejorar la compatibilidad vectorial:
Directiva | Descripción |
---|---|
simdlen(length) |
Especificar el número de carriles vectoriales. |
safelen(length) |
Especificar la distancia de dependencia vectorial. |
linear(list[ : linear-step] ) |
La asignación lineal de la variable de inducción de bucle a la suscripción de matriz. |
aligned(list[ : alignment]) |
Alineación de los datos. |
private(list) |
Especificar la privatización de datos. |
lastprivate(list) |
Especificar la privatización de datos con el valor final de la última iteración. |
reduction(reduction-identifier:list) |
Especificar las operaciones de reducción personalizadas. |
collapse(n) |
Anidamiento de bucle de fusión. |
Nota:
El compilador analiza y omite las cláusulas SIMD no efectivas con una advertencia.
Por ejemplo, el uso del código siguiente emite una advertencia:
#pragma omp simd simdlen(8)
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
warning C4849: OpenMP 'simdlen' clause ignored in 'simd' directive
Ejemplo
La directiva OpenMP SIMD proporciona a los usuarios una manera de dictar que el compilador haga que los bucles tengan compatibilidad vectorial. Al anotar un bucle con la directiva OpenMP SIMD, los usuarios pretenden tener varias iteraciones de bucle ejecutadas simultáneamente.
Por ejemplo, el siguiente bucle se anota con la directiva OpenMP SIMD. No hay paralelismo perfecto entre iteraciones de bucles, ya que hay una dependencia con versiones anteriores de a[i] a [i-1], pero debido a la directiva SIMD, el compilador todavía puede empaquetar iteraciones consecutivas de la primera instrucción en una instrucción vectorial y ejecutarlas en paralelo.
#pragma omp simd
for (i = 0; i < count; i++)
{
a[i] = a[i-1] + 1;
b[i] = *c + 1;
bar(i);
}
Por lo tanto, la siguiente forma vectorial transformada del bucle es legal porque el compilador mantiene el comportamiento secuencial de cada iteración de bucle original. En otras palabras, a[i]
se ejecuta después de a[-1]
, b[i]
después de a[i]
y la llamada a bar
se produce en último lugar.
for (i = 0; i < count; i+=4)
{
a[i:i+3] = a[i-1:i+2] + 1;
b[i:i+3] = *c + 1;
bar(i);
bar(i+1);
bar(i+2);
bar(i+3);
}
No es legal mover la referencia de memoria *c
fuera del bucle si puede tener un alias con a[i]
o b[i]
. Tampoco es legal reordenar las instrucciones dentro de una iteración original si interrumpe la dependencia secuencial. Por ejemplo, el siguiente bucle transformado no es legal:
c = b;
t = *c;
for (i = 0; i < count; i+=4)
{
a[i:i+3] = a[i-1:i+2] + 1;
bar(i); // illegal to reorder if bar[i] depends on b[i]
b[i:i+3] = t + 1; // illegal to move *c out of the loop
bar(i+1);
bar(i+2);
bar(i+3);
}