Tipos de paralelismo de datos (SIMD) (desde C++26)
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 los datos a través de recursos de ejecución paralela de datos cuando estén disponibles, como registros e instrucciones SIMD o unidades de ejecución que son controladas por un decodificador de instrucciones común.
El conjunto de tipos vectorizables comprende:
- todos los enteros y tipos carácter estándar;
- la mayoría de los tipos de punto flotante, incluidos
float,double, y los tipos de punto flotante extendidos seleccionados:std::float16_t,std::float32_t, ystd::float64_tsi están definidos; y std::complex<T>dondeTes un tipo de punto flotante vectorizable.
Un tipo de datos paralelos consiste en uno o más elementos de un tipo vectorizable subyacente, llamado tipo de elemento . El número de elementos, llamado ancho , es constante para cada tipo de datos paralelos.
El tipo de datos paralelos se refiere a todas las especializaciones habilitadas de las plantillas de clase basic_vec y basic_mask.
Un objeto de datos paralelos de tipo de datos paralelos se comporta de manera análoga a los 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 a elemento (excepto para operaciones horizontales, como reducciones, que están claramente marcadas como tales) aplicándose a cada elemento del objeto o a elementos correspondientes de dos objetos. Cada aplicación de este tipo no está secuenciada con 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 función matemáticas no constexpr) sobre objetos de datos paralelos son constexpr: es posible crear y usar objetos de datos paralelos en la evaluación de una expresión constante.
Las plantillas de alias vec y mask se definen para permitir a los usuarios especificar el ancho a un tamaño determinado. El ancho predeterminado lo determina la implementación en tiempo de compilación.
Definido en el encabezado
<simd> | |
Definido en el espacio de nombres
std::simd |
Clases principales
(C++26) |
Tipo de vector de paralelismo de datos. (plantilla de clase) |
(C++26) |
Plantilla de alias de conveniencia para basic_vec que permite especificar su anchura. (plantilla de alias) |
(C++26) |
Tipo de paralelismo de datos con el tipo de elemento bool. (plantilla de clase) |
(C++26) |
Plantilla de alias de conveniencia para basic_mask que permite especificar su anchura. (plantilla de alias) |
Indicadores de carga y almacenamiento
(C++26) |
Indicadores de carga y almacenamiento para tipos de paralelismo de datos. (plantilla de clase) |
(C++26) |
Indicador predeterminado utilizado en operaciones de carga y almacenamiento. (constante) |
(C++26) |
Indicador que habilita conversiones que no preservan el valor en operaciones de carga y almacenamiento. (constante) |
(C++26) |
Indicador de que la dirección de carga o almacenamiento está alineada según simd::alignment. (constante) |
(C++26) |
Indicador de que la dirección de carga o almacenamiento está alineada según una alineación específica. (plantilla de variables) |
Operaciones de carga y almacenamiento
Carga elementos desde un rango contiguo a basic_vec. (plantilla de función) | |
Almacena elementos de basic_vec en un rango contiguo. (plantilla de función) |
Moldes
(C++26) |
Divide un único objeto de paralelismo de datos en varios. (plantilla de función) |
(C++26) |
Concatena múltiples objetos de paralelismo de datos en uno solo. (plantilla de función) |
Algoritmos
Operaciones de mínimo/máximo elemento a elemento para basic_vec. (plantilla de función) | |
(C++26) |
Operación de acotado elemento a elemento para basic_vec. (plantilla de función) |
(C++26) |
Selección elemento a elemento mediante el operador condicional. (plantilla de función) |
Reducciones
Reduce todos los valores de basic_vec a un único valor mediante una operación binaria especificada. (plantilla de función) | |
Reducciones de basic_mask a bool. (plantilla de función) | |
(C++26) |
Reducción de basic_mask al número de valores true. (plantilla de función) |
Reducciones de basic_mask al índice del primer o último valor true. (plantilla de función) |
Permutaciones
Valores especiales para permute estático. (constante) | |
(C++26) |
Permutaciones estáticas y dinámicas de basic_vec y basic_mask. (plantilla de función) |
(C++26) |
Compresión / expansión de permutaciones de basic_vec y basic_mask según una basic_mask dada. (plantilla de función) |
Permutaciones de basic_vec desde/hacia la memoria con máscara de escritura opcional. (plantilla de función) |
Rasgos
(C++26) |
Obtiene una alineación adecuada para simd::flag_aligned. (plantilla de clase) |
(C++26) |
Cambia el tipo de elemento del tipo de paralelismo de datos. (plantilla de clase) |
(C++26) |
Cambia la anchura del tipo de paralelismo de datos. (plantilla de clase) |
Funciones matemáticas
Todas las funciones en <cmath> y <complex> están sobrecargadas para basic_vec.
| Esta sección está incompleta Razón: descripción |
Funciones de manipulación de bits
Todas las funciones de manipulación de bits en <bit> están sobrecargadas para basic_vec.
| Esta sección está incompleta Razón: descripción |
Detalles de implementación
Etiquetas ABI
Los tipos de datos paralelos basic_vec y basic_mask están asociados con etiquetas ABI . Estas etiquetas son tipos que especifican el tamaño y la representación binaria de los objetos de datos paralelos. El diseño pretende que el tamaño y la representación binaria varíen según la arquitectura de destino y las banderas 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 la máquina. El conjunto de instrucciones de la máquina elegido limita los tipos de etiquetas ABI utilizables. Las etiquetas ABI permiten a los usuarios pasar de manera segura objetos de tipo de datos paralelos a través de los límites de las unidades de traducción.
| Esta sección está incompleta |
Entidades solo de exposición
| Esta sección está incompleta Razón: necesita actualización |
using /*simd-size-type*/ = /* véase descripción */; |
(1) | (solo de exposición*) |
template< std::size_t Bytes > using /*integer-from*/ = /* véase descripción */; |
(2) | (solo de exposición*) |
template< class T, class Abi > constexpr /*simd-size-type*/ /*simd-size-v*/ = /* véase descripción */; |
(3) | (solo de exposición*) |
template< class T > constexpr std::size_t /*mask-element-size*/ = /* véase descripción */; |
(4) | (solo de exposición*) |
template< class T > concept /*constexpr-wrapper-like*/ = /* véase descripción */; |
(5) | (solo de exposición*) |
template< class T > using /*deduced-simd-t*/ = /* véase descripción */; |
(6) | (solo de exposición*) |
template< class V, class T > using /*make-compatible-simd-t*/ = /* véase descripción */; |
(7) | (solo de exposición*) |
/*simd-size-type*/ es un alias para un tipo entero con signo. La implementación es libre de elegir cualquier tipo entero con signo./*integer-from*/<Bytes> es un alias para un tipo entero con signo T tal que sizeof(T) es igual a Bytes./*simd-size-v*/<T, Abi> denota el ancho de la especialización habilitada basic_vec<T, Abi>, o 0 en caso contrario.T denota std::simd::basic_mask<Bytes, Abi>, /*mask-element-size*/<T> es igual a Bytes./*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;
x un l-valor de tipo const T. /*deduced-simd-t*/<T> es un alias equivalente a:
decltype(x + x), si el tipo dex + xes una especialización habilitada debasic_vec; de lo contrariovoid.
x un l-valor de tipo const T. /*make-compatible-simd-t*/<V, T> es un alias equivalente a:
/*deduced-simd-t*/<T>, si ese tipo no esvoid, de lo contrariostd::simd::vec<decltype(x + x), V::size()>.
| Requisitos de funciones matemáticas |
||
template< class V > concept /*simd-floating-point*/ = /* véase descripción */; |
(8) | (solo de exposición*) |
template< class... Ts > concept /*math-floating-point*/ = /* véase descripción */; |
(9) | (solo de exposición*) |
template< class... Ts > requires /*math-floating-point*/<Ts...> using /*math-common-simd-t*/ = /* véase descripción */; |
(10) | (solo de exposición*) |
template< class BinaryOp, class T > concept /*reduction-binary-operation*/ = /* véase descripción */; |
(11) | (solo de exposición*) |
/*simd-floating-point*/ se define como:
template< class V >
concept /*simd-floating-point*/ =
std::same_as<V,
std::simd::basic_vec<typename V::value_type,
typename V::abi_type>> &&
std::is_default_constructible_v<V> &&
std::floating_point<typename V::value_type>;
/*math-floating-point*/ se define como:
template< class... Ts >
concept /*math-floating-point*/ =
(/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);
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>, sisizeof...(Ts) == 1estrue- de lo contrario,
std::common_type_t</*deduced-simd-t*/<T0>, /*deduced-simd-t*/<T1>>, sisizeof...(Ts) == 2estruey/*math-floating-point*/<T0> && /*math-floating-point*/<T1>estrue, - de lo contrario,
std::common_type_t</*deduced-simd-t*/<T0>, T1>sisizeof...(Ts) == 2estruey/*math-floating-point*/<T0>estrue, - de lo contrario,
std::common_type_t<T0, /*deduced-simd-t*/<T1>>sisizeof...(Ts) == 2estrue, - 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>.
/*reduction-binary-operation*/ se define como:
template< class BinaryOp, class T >
concept /*reduction-binary-operation*/ =
requires (const BinaryOp binary_op, const std::simd::vec<T, 1> v) {
{ binary_op(v, v) } -> std::same_as<std::simd::vec<T, 1>>;
};
/*reduction-binary-operation*/<BinaryOp, T> se modela solo si:
BinaryOpes una operación binaria elemento a elemento que es conmutativa, y- Un objeto de tipo
BinaryOpes invocable con dos argumentos de tipostd::simd::basic_vec<T, Abi>para una etiqueta ABI no especificadaAbique devuelve unstd::simd::basic_vec<T, Abi>.
| Etiquetas ABI SIMD |
||
template< class T > using /*native-abi*/ = /* véase descripción */; |
(12) | (solo de exposición*) |
template< class T, /*simd-size-type*/ N > using /*deduce-abi-t*/ = /* véase descripción */; |
(13) | (solo de exposición*) |
/*native-abi*/<T> es un alias definido por la implementación para una etiqueta ABI. Esta es la etiqueta ABI principal que debe utilizarse para una vectorización explícita eficiente. Como resultado, basic_vec<T, /*native-abi*/<T>> es una especialización habilitada./*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 aN,std::simd::basic_vec<T, /*deduce-abi-t*/<T, N>>es una especialización habilitada, ystd::simd::basic_mask<sizeof(T), /*deduce-abi-t*/</*integer-from*/<sizeof(T)>, N>>es una especialización habilitada.
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.| Indicadores de carga y almacenamiento |
||
struct /*convert-flag*/; |
(14) | (solo de exposición*) |
struct /*aligned-flag*/; |
(15) | (solo de exposición*) |
template< std::size_t N > struct /*overaligned-flag*/; |
(16) | (solo de exposición*) |
std::simd::flags. Consulte indicadores de carga y almacenamiento para sus usos correspondientes.Notas
| Macro de prueba de característica | |||
|---|---|---|---|
__cpp_lib_simd |
202411L |
(C++26) | Tipos y operaciones de paralelismo de datos |
202603L |
(C++26) | Difusión consteval que preserva el valor a simd::vec
| |
__cpp_lib_simd_complex |
202502L |
(C++26) | Valores complejos entrelazados |
__cpp_lib_simd_permutations |
202506L |
(C++26) | Permutaciones SIMD |
Ejemplo
#include <iostream>
#include <simd>
#include <string_view>
namespace simd = std::simd;
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 simd::basic_vec<int, A> my_abs(simd::basic_vec<int, A> x)
{
return simd::select(x < 0, -x, x);
}
int main()
{
constexpr simd::vec<int> a = 1;
println("a", a);
constexpr simd::vec<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 = simd::reduce(e);
std::cout << "producto interno: " << inner_product << '\n';
constexpr simd::vec<double, 16> x([](int i) { return i; });
println("x", x);
// Las funciones matemáticas sobrecargadas se definen en <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
producto interno: 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 1Véase también
| Tipo vectorial de paralelismo de datos. (plantilla de clase) | |
| arrays numéricos, máscaras de arrays y secciones de array. (plantilla de clase) |