Namespaces
Variants

Data-parallel types (SIMD) (since C++26)

From cppreference.net

La biblioteca proporciona tipos de datos paralelos y operaciones sobre estos tipos: tipos portátiles para declarar explícitamente el paralelismo de datos y estructurar datos mediante recursos de ejecución de datos paralelos donde estén disponibles, como SIMD registros e instrucciones o unidades de ejecución que son controladas por un decodificador de instrucciones común.

El conjunto de tipos vectorizables comprende:

Un tipo de datos paralelos consiste en uno o más elementos de un tipo subyacente vectorizable, llamado tipo de elemento  . El número de elementos, llamado ancho  , es constante para cada tipo de datos paralelos.

El tipo de datos paralelo se refiere a todas las especializaciones habilitadas de las plantillas de clase basic_simd y basic_simd_mask .

Un objeto de datos paralelos de tipo de datos paralelos se comporta de manera análoga a objetos de tipo T . Pero mientras T almacena y manipula un solo valor, el tipo de datos paralelos con el tipo de elemento T almacena y manipula múltiples valores.

Cada operación sobre un objeto de datos paralelos actúa elemento por elemento (excepto para operaciones horizontales, como las reducciones, que están claramente marcadas como tales) aplicándose a cada elemento del objeto o a elementos correspondientes de dos objetos. Cada una de estas aplicaciones no está secuenciada respecto a las demás. Esta regla simple expresa el paralelismo de datos y será utilizada por el compilador para generar instrucciones SIMD y/o flujos de ejecución independientes.

Todas las operaciones (excepto las sobrecargas de funciones matemáticas no constexpr ) en objetos de datos paralelos son constexpr : es posible crear y utilizar objetos de datos paralelos en la evaluación de una expresión constante.

Las plantillas de alias simd y simd_mask se definen para permitir a los usuarios especificar el ancho a un tamaño determinado. El ancho predeterminado es determinado por la implementación en tiempo de compilación.

Definido en el encabezado <simd>
Definido en el espacio de nombres std::datapar

Contenidos

Clases principales

tipo vectorial de procesamiento de datos en paralelo
(plantilla de clase)
plantilla de alias conveniente para basic_simd que puede especificar su ancho
(plantilla de alias)
tipo de procesamiento de datos en paralelo con el tipo de elemento bool
(plantilla de clase)
plantilla de alias conveniente para basic_simd_mask que puede especificar su ancho
(plantilla de alias)

Banderas de carga y almacenamiento

banderas de carga y almacenamiento para tipos de datos paralelos
(plantilla de clase)
bandera predeterminada utilizada en operaciones de carga y almacenamiento
(constante)
bandera que habilita conversiones que no preservan valores en operaciones de carga y almacenamiento
(constante)
bandera que indica la alineación de la dirección de carga-almacenamiento con algún almacenamiento especificado al valor de datapar::alignment
(constante)
bandera que indica la alineación de la dirección de carga-almacenamiento con algún almacenamiento especificado a la alineación especificada
(plantilla de variable)

Operaciones de carga y almacenamiento

carga elementos desde un rango contiguo a basic_simd
(plantilla de función)
almacena elementos desde basic_simd a un rango contiguo
(plantilla de función)

Conversiones

divide un único objeto de paralelismo de datos en múltiples objetos
(plantilla de función)
concatena múltiples objetos de paralelismo de datos en uno solo
(plantilla de función)

Algoritmos

operaciones min/max elemento a elemento para basic_simd
(plantilla de función)
operación clamp elemento a elemento para basic_simd
(plantilla de función)
selección elemento a elemento usando operador condicional
(plantilla de función)

Reducciones

reduce todos los valores en basic_simd sobre una operación binaria especificada a un único valor
(plantilla de función)
reducciones de basic_simd_mask a bool
(plantilla de función)
reducción de basic_simd_mask al número de valores true
(plantilla de función)
reducciones de basic_simd_mask al índice del primer o último valor true
(plantilla de función)

Rasgos

obtiene una alineación apropiada para datapar::flag_aligned
(plantilla de clase)
cambia el tipo de elemento del tipo de datos paralelos
(plantilla de clase)
cambia el ancho del tipo de datos paralelos
(plantilla de clase)

Funciones matemáticas

Todas las funciones en <cmath> y <complex> están sobrecargadas para basic_simd .

Funciones de manipulación de bits

Todas las funciones de manipulación de bits en <bit> están sobrecargadas para basic_simd .

Detalles de implementación

Etiquetas ABI

Los tipos de datos paralelos basic_simd y basic_simd_mask están asociados con etiquetas ABI  . Estas etiquetas son tipos que especifican el tamaño y la representación binaria de objetos de datos paralelos. El diseño pretende que el tamaño y la representación binaria varíen según la arquitectura objetivo y los flags del compilador. La etiqueta ABI, junto con el tipo de elemento, determina el ancho.

La etiqueta ABI permanece independiente de la selección del conjunto de instrucciones de máquina. El conjunto de instrucciones de máquina elegido limita los tipos de etiquetas ABI utilizables. Las etiquetas ABI permiten a los usuarios pasar de forma segura objetos de tipo data-parallel a través de los límites de las unidades de traducción.

Entidades solo para exposición

using /*simd-size-type*/ = /* ver descripción */ ;
(1) ( solo para exposición* )
template < std:: size_t Bytes >
using /*integer-from*/ = /* ver descripción */ ;
(2) ( solo para exposición* )
template < class T, class Abi >
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* ver descripción */ ;
(3) ( solo para exposición* )
template < class T >
constexpr std:: size_t /*mask-element-size*/ = /* ver descripción */ ;
(4) ( solo para exposición* )
template < class T >
concept /*constexpr-wrapper-like*/ = /* ver descripción */ ;
(5) ( solo para exposición* )
template < class T >
using /*deduced-simd-t*/ = /* ver descripción */ ;
(6) ( solo para exposición* )
template < class V, class T >
using /*make-compatible-simd-t*/ = /* ver descripción */ ;
(7) ( solo para exposición* )
1) /*simd-size-type*/ es un alias para un tipo entero con signo. La implementación es libre de elegir cualquier tipo entero con signo.
2) /*integer-from*/ < Bytes > es un alias para un tipo entero con signo T tal que sizeof ( T ) es igual a Bytes .
3) /*simd-size-v*/ < T, Abi > denota el ancho de la especialización habilitada basic_simd<T, Abi> , o 0 en caso contrario.
4) Si T denota std :: datapar :: basic_simd_mask < Bytes, Abi > , /*mask-element-size*/ < T > es igual a Bytes .
5) El concepto /*constexpr-wrapper-like*/ se define como:
template< class T >
concept /*constexpr-wrapper-like*/ =
    std::convertible_to<T, decltype(T::value)> &&
    std::equality_comparable_with<T, decltype(T::value)> &&
    std::bool_constant<T() == T::value>::value &&
    std::bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
6) Sea x un lvalue de tipo const T . /*deduced-simd-t*/ < T > es un alias equivalente a:
  • decltype ( x + x ) , si el tipo de x + x es una especialización habilitada de basic_simd ; de lo contrario
  • void .
7) Sea x un lvalue de tipo const T . /*make-compatible-simd-t*/ < V, T > es un alias equivalente a:
  • /*deduced-simd-t*/ < T > , si ese tipo no es void , de lo contrario
  • std :: datapar :: simd < decltype ( x + x ) , V​ :: ​size ( ) > .
Requisitos de funciones matemáticas
template < class V >
concept /*simd-floating-point*/ = /* see description */ ;
(8) ( solo para exposición* )
template < class ... Ts >
concept /*math-floating-point*/ = /* see description */ ;
(9) ( solo para exposición* )
template < class ... Ts >

requires /*math-floating-point*/ < Ts... >

using /*math-common-simd-t*/ = /* see description */ ;
(10) ( solo para exposición* )
template < class BinaryOp, class T >
concept /*reduction-binary-operation*/ = /* see description */ ;
(11) ( solo para exposición* )
8) El concepto /*simd-floating-point*/ se define como:
template< class V >
concept /*simd-floating-point*/ =
    std::same_as<V,
                 std::datapar::basic_simd<typename V::value_type,
                 typename V::abi_type>> &&
    std::is_default_constructible_v<V> && 
    std::floating_point<typename V::value_type>;
9) El concepto /*math-floating-point*/ se define como:
template< class... Ts >
concept /*math-floating-point*/ =
    (/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);
10) Sea T0 que denota Ts... [ 0 ] , T1 que denota Ts... [ 1 ] , y TRest que denota un paquete tal que T0, T1, TRest... es equivalente a Ts... . Entonces, /*math-common-simd-t*/ < Ts... > es un alias equivalente a:
  • /*deduced-simd-t*/ < T0 > , si sizeof... ( Ts ) == 1 es true
  • de lo contrario, std:: common_type_t < /*deduced-simd-t*/ < T0 > , /*deduced-simd-t*/ < T1 >> , si sizeof... ( Ts ) == 2 es true y /*math-floating-point*/ < T0 > && /*math-floating-point*/ < T1 > es true ,
  • de lo contrario, std:: common_type_t < /*deduced-simd-t*/ < T0 > , T1 > si sizeof... ( Ts ) == 2 es true y /*math-floating-point*/ < T0 > es true ,
  • de lo contrario, std:: common_type_t < T0, /*deduced-simd-t*/ < T1 >> si sizeof... ( Ts ) == 2 es true ,
  • de lo contrario, std:: common_type_t < /*math-common-simd-t*/ < T0, T1 > , TRest... > , si /*math-common-simd-t*/ < T0, T1 > es un tipo válido,
  • de lo contrario, std:: common_type_t < /*math-common-simd-t*/ < TRest... > , T0, T1 > .
11) El concepto /*reduction-binary-operation*/ se define como:
template< class BinaryOp, class T >
concept /*reduction-binary-operation*/ =
    requires (const BinaryOp binary_op, const std::datapar::simd<T, 1> v) {
        { binary_op(v, v) } -> std::same_as<std::datapar::simd<T, 1>>;
    };

/*reduction-binary-operation*/ < BinaryOp, T > se modela solo si:

  • BinaryOp es una operación binaria elemento a elemento que es conmutativa, y
  • Un objeto de tipo BinaryOp es invocable con dos argumentos de tipo std :: datapar :: basic_simd < T, Abi > para una etiqueta ABI no especificada Abi que retorna un std :: datapar :: basic_simd < T, Abi > .
Etiquetas ABI SIMD
template < class T >
using /*native-abi*/ = /* ver descripción */ ;
(12) ( solo para exposición* )
template < class T, /*simd-size-type*/ N >
using /*deduce-abi-t*/ = /* ver descripción */ ;
(13) ( solo para exposición* )
12) /*native-abi*/ < T > es un alias definido por la implementación para una etiqueta ABI. Esta es la etiqueta ABI principal para usar en vectorización explícita eficiente. Como resultado, basic_simd < T, /*native-abi*/ < T >> es una especialización habilitada.
13) /*deduce-abi-t*/ < T, N > es un alias que nombra un tipo de etiqueta ABI tal que:
  • /*simd-size-v*/ < T, /*deduce-abi-t*/ < T, N >> es igual a N ,
  • std :: datapar :: basic_simd < T, /*deduce-abi-t*/ < T, N >> es una especialización habilitada, y
  • std :: datapar :: basic_simd_mask < sizeof ( T ) , /*deduce-abi-t*/ < /*integer-from*/ < sizeof ( T ) > , N >> es una especialización habilitada.
Solo está definido si T es un tipo vectorizable, y N > 0 && N <= M es true , donde M es un máximo definido por la implementación que es al menos 64 y puede diferir dependiendo de T .
Banderas de carga y almacenamiento
struct /*convert-flag*/ ;
(14) ( solo para exposición* )
struct /*aligned-flag*/ ;
(15) ( solo para exposición* )
template < std:: size_t N >
struct /*overaligned-flag*/ ;
(16) ( solo para exposición* )
14-16) Estos tipos de etiqueta se utilizan como argumento de plantilla de std::datapar::flags . Consulte banderas de carga y almacenamiento para sus usos correspondientes.

Notas

Macro de prueba de características Valor Std Característica
__cpp_lib_simd 202411L (C++26) Tipos y operaciones de paralelismo de datos
__cpp_lib_simd_complex 202502L (C++26) Soporte de valores complejos entrelazados en std::datapar::simd

Ejemplo

#include <iostream>
#include <simd>
#include <string_view>
void println(std::string_view name, auto const& a)
{
    std::cout << name << ": ";
    for (std::size_t i{}; i != a.size(); ++i)
        std::cout << a[i] << ' ';
    std::cout << '\n';
}
template<class A>
constexpr std::datapar::basic_simd<int, A> my_abs(std::datapar::basic_simd<int, A> x)
{
    return std::datapar::select(x < 0, -x, x);
}
int main()
{
    constexpr std::datapar::simd<int> a = 1;
    println("a", a);
    constexpr std::datapar::simd<int> b([](int i) { return i - 2; });
    println("b", b);
    constexpr auto c = a + b;
    println("c", c);
    constexpr auto d = my_abs(c);
    println("d", d);
    constexpr auto e = d * d;
    println("e", e);
    constexpr auto inner_product = std::datapar::reduce(e);
    std::cout << "inner product: " << inner_product << '\n';
    constexpr std::datapar::simd<double, 16> x([](int i) { return i; });
    println("x", x);
    // overloaded math functions are defined in <simd>
    println("cos²(x) + sin²(x)", std::pow(std::cos(x), 2) + std::pow(std::sin(x), 2));
}

Salida:

a: 1 1 1 1 
b: -2 -1 0 1 
c: -1 0 1 2 
d: 1 0 1 2 
e: 1 0 1 4 
inner product: 6
x: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
cos²(x) + sin²(x): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Véase también

arrays numéricos, máscaras de array y segmentos de array
(plantilla de clase)

Enlaces externos

1. La implementación de ISO/IEC TS 19570:2018 Sección 9 "Tipos de Datos Paralelos" — github.com
2. Implementación TS disponible para GCC/libstdc++ ( std::experimental::simd se incluye con GCC-11) — gcc.gnu.org