SIMD library
La biblioteca SIMD proporciona tipos portátiles para declarar explícitamente el paralelismo de datos y estructurar datos para un acceso SIMD más eficiente.
Un objeto de tipo
simd<T>
se comporta de manera análoga a objetos de tipo
T
. Pero mientras
T
almacena y manipula un valor,
simd<T>
almacena y manipula múltiples valores (llamados
width
pero identificados como
size
para consistencia con el resto de la biblioteca estándar; cf.
simd_size
).
Cada operador y operación en
simd<T>
actúa
elemento por elemento
(excepto las operaciones
horizontales
, que están claramente marcadas como tales). Esta regla simple expresa paralelismo de datos y será utilizada por el compilador para generar instrucciones SIMD y/o flujos de ejecución independientes.
El ancho de los tipos
simd<T>
y
native_simd<T>
está determinado por la implementación en tiempo de compilación. En contraste, el ancho del tipo
fixed_size_simd<T, N>
está fijado por el desarrollador a un tamaño específico.
Un patrón recomendado para usar una combinación de diferentes tipos SIMD con alta eficiencia utiliza native_simd y rebind_simd :
#include <experimental/simd> namespace stdx = std::experimental; using floatv = stdx::native_simd<float>; using doublev = stdx::rebind_simd_t<double, floatv>; using intv = stdx::rebind_simd_t<int, floatv>;
Esto asegura que el conjunto de tipos tenga el mismo ancho y por lo tanto puedan ser convertidos entre sí. Una conversión con ancho no coincidente no está definida porque podría eliminar valores o tener que inventar valores. Para operaciones de cambio de tamaño, la biblioteca SIMD proporciona las funciones split y concat .
|
Definido en el encabezado
<experimental/simd>
|
Contenidos |
Clases principales
|
(parallelism TS v2)
|
tipo vectorial de procesamiento de datos en paralelo
(plantilla de clase) |
|
(parallelism TS v2)
|
tipo de procesamiento de datos en paralelo con el tipo de elemento bool
(plantilla de clase) |
Etiquetas ABI
|
Definido en el espacio de nombres
std::experimental::simd_abi
|
|
|
(parallelism TS v2)
|
tipo etiqueta para almacenar un único elemento
(typedef) |
|
(parallelism TS v2)
|
tipo etiqueta para almacenar un número especificado de elementos
(plantilla de alias) |
|
(parallelism TS v2)
|
tipo etiqueta que garantiza compatibilidad ABI
(plantilla de alias) |
|
(parallelism TS v2)
|
tipo etiqueta que es más eficiente
(plantilla de alias) |
|
(parallelism TS v2)
|
el número máximo de elementos garantizado para ser soportado por fixed
(constante) |
|
(parallelism TS v2)
|
obtiene un tipo ABI para un tipo de elemento y número de elementos dados
(plantilla de clase) |
Etiquetas de alineación
|
(parallelism TS v2)
|
indicador de alineación de la dirección de carga/almacenamiento a alineación de elemento
(clase) |
|
(parallelism TS v2)
|
indicador de alineación de la dirección de carga/almacenamiento a alineación de vector
(clase) |
|
(parallelism TS v2)
|
indicador de alineación de la dirección de carga/almacenamiento a la alineación especificada
(plantilla de clase) |
Expresión Where
|
(parallelism TS v2)
|
elementos seleccionados con operaciones no mutantes
(plantilla de clase) |
|
(parallelism TS v2)
|
elementos seleccionados con operaciones mutantes
(plantilla de clase) |
|
(parallelism TS v2)
|
produce const_where_expression y where_expression
(plantilla de función) |
Conversiones de Tipo
|
(parallelism TS v2)
|
conversión elemento a elemento mediante static_cast
(plantilla de función) |
|
(parallelism TS v2)
|
conversión elemento a elemento de ABI
(plantilla de función) |
|
(parallelism TS v2)
|
divide un único objeto simd en múltiples
(plantilla de función) |
|
(parallelism TS v2)
|
concatena múltiples objetos simd en uno único
(plantilla de función) |
Algoritmos
|
(parallelism TS v2)
|
operación min elemento por elemento
(plantilla de función) |
|
(parallelism TS v2)
|
operación max elemento por elemento
(plantilla de función) |
|
(parallelism TS v2)
|
operación minmax elemento por elemento
(plantilla de función) |
|
(parallelism TS v2)
|
operación clamp elemento por elemento
(plantilla de función) |
Reducción
|
(parallelism TS v2)
|
reduce el vector a un solo elemento
(plantilla de función) |
Reducción de máscara
|
(parallelism TS v2)
|
reducciones de
simd_mask
a
bool
(plantilla de función) |
|
(parallelism TS v2)
|
reducción de
simd_mask
al número de valores
true
(plantilla de función) |
|
(parallelism TS v2)
|
reducciones de
simd_mask
al índice del primer o último valor
true
(plantilla de función) |
Rasgos
|
(parallelism TS v2)
|
verifica si un tipo es un
simd
o
simd_mask
type
(plantilla de clase) |
|
(parallelism TS v2)
|
verifica si un tipo es un tipo de etiqueta ABI
(plantilla de clase) |
|
(parallelism TS v2)
|
verifica si un tipo es un tipo de bandera simd
(plantilla de clase) |
|
(parallelism TS v2)
|
obtiene el número de elementos de un tipo de elemento y etiqueta ABI dados
(plantilla de clase) |
|
(parallelism TS v2)
|
obtiene una alineación apropiada para
vector_aligned
(plantilla de clase) |
|
(parallelism TS v2)
|
cambia el tipo de elemento o el número de elementos de
simd
o
simd_mask
(plantilla de clase) |
Funciones matemáticas
Todas las funciones en
<cmath>
, excepto las funciones matemáticas especiales, están sobrecargadas para
simd
.
Ejemplo
#include <experimental/simd> #include <iostream> #include <string_view> namespace stdx = std::experimental; void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != std::size(a); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> stdx::simd<int, A> my_abs(stdx::simd<int, A> x) { where(x < 0, x) = -x; return x; } int main() { const stdx::native_simd<int> a = 1; println("a", a); const stdx::native_simd<int> b([](int i) { return i - 2; }); println("b", b); const auto c = a + b; println("c", c); const auto d = my_abs(c); println("d", d); const auto e = d * d; println("e", e); const auto inner_product = stdx::reduce(e); std::cout << "inner product: " << inner_product << '\n'; const stdx::fixed_size_simd<long double, 16> x([](int i) { return i; }); println("x", x); println("cos²(x) + sin²(x)", stdx::pow(stdx::cos(x), 2) + stdx::pow(stdx::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
|
arreglos numéricos, máscaras de arreglo y segmentos de arreglo
(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
|