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
Plantilla:cpp/numeric/simd/dsc basic vecPlantilla:cpp/numeric/simd/dsc vecPlantilla:cpp/numeric/simd/dsc basic maskPlantilla:cpp/numeric/simd/dsc maskIndicadores de carga y almacenamiento
Plantilla:cpp/numeric/simd/dsc flagsPlantilla:cpp/numeric/simd/dsc flag defaultPlantilla:cpp/numeric/simd/dsc flag convertPlantilla:cpp/numeric/simd/dsc flag alignedPlantilla:cpp/numeric/simd/dsc flag overalignedOperaciones de carga y almacenamiento
Plantilla:cpp/numeric/simd/dsc loadPlantilla:cpp/numeric/simd/dsc storeMoldes
Plantilla:cpp/numeric/simd/dsc chunkPlantilla:cpp/numeric/simd/dsc catAlgoritmos
Plantilla:cpp/numeric/simd/dsc min maxPlantilla:cpp/numeric/simd/dsc clampPlantilla:cpp/numeric/simd/dsc selectReducciones
Plantilla:cpp/numeric/simd/dsc reducePlantilla:cpp/numeric/simd/dsc all any none ofPlantilla:cpp/numeric/simd/dsc reduce countPlantilla:cpp/numeric/simd/dsc reduce min max indexPermutaciones
Plantilla:cpp/numeric/simd/dsc zero uninit elementPlantilla:cpp/numeric/simd/dsc permutePlantilla:cpp/numeric/simd/dsc mask permutePlantilla:cpp/numeric/simd/dsc memory permuteRasgos
Plantilla:cpp/numeric/simd/dsc alignmentPlantilla:cpp/numeric/simd/dsc rebindPlantilla:cpp/numeric/simd/dsc resizeFunciones 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 1
Véase también
Plantilla:cpp/experimental/simd/dsc simd| arrays numéricos, máscaras de arrays y secciones de array. (plantilla de clase) |