Extensión SIMDSIMD Extension

Visual C++ actualmente es compatible con el estándar OpenMP 2.0, sin embargo, Visual Studio 2019 también ahora ofrece funcionalidad SIMD.Visual C++ currently supports the OpenMP 2.0 standard, however Visual Studio 2019 also now offers SIMD functionality.

Nota

Para utilizar SIMD, -openmp:experimental compile con el conmutador que habilita -openmp funciones OpenMP adicionales que no están disponibles cuando se utiliza el conmutador.To use SIMD, compile with the -openmp:experimental switch that enables additional OpenMP features not available when using the -openmp switch.

El -openmp:experimental interruptor -openmpsubsume, lo que significa que todas las características de OpenMP 2.0 están incluidas en su uso.The -openmp:experimental switch subsumes -openmp, meaning all OpenMP 2.0 features are included in its use.

Para obtener más información, vea Extensión DE SIMD a C++ OpenMP en Visual Studio.For more information, see SIMD Extension to C++ OpenMP in Visual Studio.

OpenMP SIMD en Visual C++OpenMP SIMD in Visual C++

OpenMP SIMD, introducido en el estándar OpenMP 4.0, se dirige a la fabricación de bucles aptos para vectores.OpenMP SIMD, introduced in the OpenMP 4.0 standard, targets making vector-friendly loops. Mediante el simd uso de la directiva antes de un bucle, el compilador puede omitir las dependencias vectoriales, hacer que el bucle sea lo más apto para vectores como sea posible y respetar la intención de los usuarios de que varias iteraciones de bucle se ejecuten simultáneamente.By using the simd directive before a loop, the compiler can ignore vector dependencies, make the loop as vector-friendly as possible, and respect the users’ intention to have multiple loop iterations executed simultaneously.

    #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 #pragma vector #pragma ivdepno OpenMP similares como y, sin embargo, con OpenMP SIMD, el compilador puede hacer más, como:Visual C++ provides similar non-OpenMP loop pragmas like #pragma vector and #pragma ivdep, however with OpenMP SIMD, the compiler can do more, like:

  • Siempre se permite ignorar las dependencias vectoriales actuales.Always allowed to ignore present vector dependencies.
  • /fp:fastse habilita dentro del bucle./fp:fast is enabled within the loop.
  • Los bucles externos y los bucles con llamadas de función son aptos para vectores.Outer loops and loops with function calls are vector-friendly.
  • Los bucles anidados se pueden combinar en un bucle y hacer que sean aptos para vectores.Nested loops can be coalesced into one loop and made vector-friendly.
  • Aceleración #pragma omp for simd híbrida con para permitir vectores de grano grueso y de grano fino.Hybrid acceleration with #pragma omp for simd to enable coarse-grained multi-threading and fine-grained vectors.

Para bucles basados en vectores, el compilador permanece en silencio a menos que utilice un modificador de registro de soporte vectorial:For vector-friendly loops, the compiler remains silent unless you use a vector-support log switch:

    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

Para bucles no aptos para vectores, el compilador emite cada mensaje:For non-vector-friendly loops, the compiler issues each a message:

    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áusulasClauses

La directiva SIMD de OpenMP también puede tomar las siguientes cláusulas para mejorar la compatibilidad con vectores:The OpenMP SIMD directive can also take the following clauses to enhance vector-support:

DirectivaDirective DescripciónDescription
simdlen(length) Especifique el número de carriles vectoriales.Specify the number of vector lanes.
safelen(length) Especifique la distancia de dependencia vectorial.Specify the vector dependency distance.
linear(list[ : linear-step])linear(list[ : linear-step]) La asignación lineal de la variable de inducción de bucle a la suscripción de matriz.The linear mapping from loop induction variable to array subscription.
aligned(list[ : alignment]) La alineación de los datos.The alignment of data.
private(list) Especifique la privatización de datos.Specify data privatization.
lastprivate(list) Especifique la privatización de datos con el valor final de la última iteración.Specify data privatization with final value from the last iteration.
reduction(reduction-identifier:list) Especifique operaciones de reducción personalizadas.Specify customized reduction operations.
collapse(n) Nido de bucle de fusión.Coalescing loop nest.

Nota

El compilador analiza e ignora las cláusulas SIMD no eficaces con una advertencia.Non-effective SIMD clauses are parsed and ignored by the compiler with a warning.

Por ejemplo, el uso del código siguiente emite una advertencia:For example, use of the following code issues a warning:

   #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

EjemploExample

La directiva SIMD de OpenMP proporciona a los usuarios una manera de dictar el compilador hacer bucles aptos para vectores.The OpenMP SIMD directive provides users a way to dictate the compiler make loops vector-friendly. Al anotar un bucle con la directiva OpenMP SIMD, los usuarios tienen la intención de ejecutar varias iteraciones de bucle simultáneamente.By annotating a loop with the OpenMP SIMD directive, users intend to have multiple loop iterations executed simultaneously.

Por ejemplo, el siguiente bucle se anota con la directiva OpenMP SIMD.For example, the following loop is annotated with the OpenMP SIMD directive. No hay un paralelismo perfecto entre las iteraciones de bucle, ya que hay una dependencia hacia atrás 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.There's no perfect parallelism among loop iterations since there's a backward dependency from a[i] to a[i-1], but because of the SIMD directive the compiler is still allowed to pack consecutive iterations of the first statement into one vector instruction and run them in parallel.

    #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.Therefore, the following transformed vector form of the loop is legal because the compiler keeps the sequential behavior of each original loop iteration. En otras a[i] palabras, a[-1] b[i] se a[i] ejecuta después bar de , es después y la llamada a sucede en último lugar.In other words, a[i] is executed after a[-1], b[i] is after a[i] and the call to bar happens last.

    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 *c referencia de memoria fuera del a[i] b[i]bucle si puede alias con o .It's not legal to move the memory reference *c out of the loop if it may alias with a[i] or b[i]. Tampoco es legal reordenar las instrucciones dentro de una iteración original si rompe la dependencia secuencial.It's also not legal to reorder the statements inside one original iteration if it breaks the sequential dependency. Por ejemplo, el siguiente bucle transformado no es legal:For example, the following transformed loop isn't 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);
    }

Consulte tambiénSee also

/openmp (Habilitar la compatibilidad con OpenMP 2.0)/openmp (Enable OpenMP 2.0 Support)