Data-parallel types (SIMD) (since 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 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:
- todos los tipos estándar de enteros y caracteres;
- la mayoría de los tipos de punto flotante incluyendo float , double , y los tipos de punto flotante extendidos seleccionados: std:: float16_t , std:: float32_t , y std:: float64_t si están definidos; y
-
std::
complex
<
T
>
donde
Tes un tipo de punto flotante vectorizable.
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
|
(C++26)
|
tipo vectorial de procesamiento de datos en paralelo
(plantilla de clase) |
|
(C++26)
|
plantilla de alias conveniente para
basic_simd
que puede especificar su ancho
(plantilla de alias) |
|
(C++26)
|
tipo de procesamiento de datos en paralelo con el tipo de elemento
bool
(plantilla de clase) |
|
(C++26)
|
plantilla de alias conveniente para
basic_simd_mask
que puede especificar su ancho
(plantilla de alias) |
Banderas de carga y almacenamiento
|
(C++26)
|
banderas de carga y almacenamiento para tipos de datos paralelos
(plantilla de clase) |
|
(C++26)
|
bandera predeterminada utilizada en operaciones de carga y almacenamiento
(constante) |
|
(C++26)
|
bandera que habilita conversiones que no preservan valores en operaciones de carga y almacenamiento
(constante) |
|
(C++26)
|
bandera que indica la alineación de la dirección de carga-almacenamiento con algún almacenamiento especificado al valor de
datapar::alignment
(constante) |
|
(C++26)
|
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
|
(C++26)
|
divide un único objeto de paralelismo de datos en múltiples objetos
(plantilla de función) |
|
(C++26)
|
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) |
|
|
(C++26)
|
operación clamp elemento a elemento para
basic_simd
(plantilla de función) |
|
(C++26)
|
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) |
|
|
(C++26)
|
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
|
(C++26)
|
obtiene una alineación apropiada para
datapar::flag_aligned
(plantilla de clase) |
|
(C++26)
|
cambia el tipo de elemento del tipo de datos paralelos
(plantilla de clase) |
|
(C++26)
|
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
.
|
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_simd
.
|
Esta sección está incompleta
Razón: descripción |
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.
| Esta sección está incompleta |
Entidades solo para exposición
|
Esta sección está incompleta
Razón: necesita actualizació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* ) |
T
tal que
sizeof
(
T
)
es igual a
Bytes
.
basic_simd<T, Abi>
, o
0
en caso contrario.
T
denota
std
::
datapar
::
basic_simd_mask
<
Bytes, Abi
>
,
/*mask-element-size*/
<
T
>
es igual a
Bytes
.
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;
-
decltype
(
x
+
x
)
, si el tipo de
x
+
x
es una especialización habilitada de
basic_simd; de lo contrario - void .
- /*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...
>
|
(10) | ( solo para exposición* ) |
|
template
<
class
BinaryOp,
class
T
>
concept /*reduction-binary-operation*/ = /* see description */ ; |
(11) | ( solo para exposición* ) |
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>;
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 > , 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 > .
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:
-
-
BinaryOpes una operación binaria elemento a elemento que es conmutativa, y -
Un objeto de tipo
BinaryOpes invocable con dos argumentos de tipo std :: datapar :: basic_simd < T, Abi > para una etiqueta ABI no especificadaAbique 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* ) |
- /*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.
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* ) |
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
|