Data-parallel types (SIMD) (since C++26)
Die Bibliothek stellt datenparallele Typen und Operationen auf diesen Typen bereit: portable Typen zur expliziten Angabe von Datenparallelität und Strukturierung von Daten durch datenparallele Ausführungsressourcen, wo verfügbar, wie etwa SIMD Register und Instruktionen oder Ausführungseinheiten, die von einem gemeinsamen Instruktionsdecoder gesteuert werden.
Die Menge der vectorizable types umfasst:
- alle Standard-Ganzzahl- und Zeichentypen;
- die meisten Gleitkommatypen einschließlich float , double , und die ausgewählten erweiterten Gleitkommatypen: std:: float16_t , std:: float32_t , und std:: float64_t falls definiert; und
-
std::
complex
<
T
>
wobei
Tein vektorisierbarer Gleitkommatyp ist.
Ein datenparalleler Typ besteht aus einem oder mehreren Elementen eines zugrundeliegenden vektorisierbaren Typs, genannt der Elementtyp . Die Anzahl der Elemente, genannt die Breite , ist für jeden datenparallelen Typ konstant.
Der datenparallele Typ bezieht sich auf alle aktivierten Spezialisierungen der Klassentemplates
basic_simd
und
basic_simd_mask
.
Ein
Datenparallel-Objekt
vom Datenparallel-Typ verhält sich analog zu Objekten des Typs
T
. Während jedoch
T
einen einzelnen Wert speichert und manipuliert, speichert und manipuliert der Datenparallel-Typ mit dem Elementtyp
T
mehrere Werte.
Jede Operation auf einem datenparallelen Objekt wirkt elementweise (mit Ausnahme horizontaler Operationen wie Reduktionen, die eindeutig als solche gekennzeichnet sind) und wendet sich auf jedes Element des Objekts oder auf entsprechende Elemente zweier Objekte an. Jede solche Anwendung ist ungeordnet in Bezug auf die anderen. Diese einfache Regel drückt Datenparallelismus aus und wird vom Compiler genutzt, um SIMD-Befehle und/oder unabhängige Ausführungsströme zu erzeugen.
Alle Operationen (außer nicht- constexpr Mathematik-Funktionsüberladungen) auf datenparallelen Objekten sind constexpr : es ist möglich, datenparallele Objekte in der Auswertung eines konstanten Ausdrucks zu erstellen und zu verwenden.
Alias-Templates
simd
und
simd_mask
werden definiert, um Benutzern zu ermöglichen, die Breite auf eine bestimmte Größe festzulegen. Die Standardbreite wird zur Compile-Zeit durch die Implementierung bestimmt.
|
Definiert in Header
<simd>
|
|
|
Definiert in Namespace
std::datapar
|
Inhaltsverzeichnis |
Hauptklassen
|
(C++26)
|
Datenparalleler Vektortyp
(Klassentemplate) |
|
(C++26)
|
Bequemlichkeits-Alias-Template für
basic_simd
, das seine Breite angeben kann
(Alias-Template) |
|
(C++26)
|
Datenparalleler Typ mit dem Elementtyp
bool
(Klassentemplate) |
|
(C++26)
|
Bequemlichkeits-Alias-Template für
basic_simd_mask
, das seine Breite angeben kann
(Alias-Template) |
Lade- und Speicherflags
|
(C++26)
|
Lade- und Speicher-Flags für datenparallele Typen
(Klassentemplate) |
|
(C++26)
|
Standard-Flag für Lade- und Speicheroperationen
(Konstante) |
|
(C++26)
|
Flag zur Aktivierung nicht wertbewahrender Konvertierungen bei Lade- und Speicheroperationen
(Konstante) |
|
(C++26)
|
Flag zur Angabe der Ausrichtung der Lade-Speicher-Adresse an einem bestimmten Speicher auf den Wert von
datapar::alignment
(Konstante) |
|
(C++26)
|
Flag zur Angabe der Ausrichtung der Lade-Speicher-Adresse an einem bestimmten Speicher auf die spezifizierte Ausrichtung
(Variablentemplate) |
Lade- und Speicheroperationen
lädt Elemente aus einem zusammenhängenden Bereich in
basic_simd
(Funktions-Template) |
|
speichert Elemente aus
basic_simd
in einen zusammenhängenden Bereich
(Funktions-Template) |
Casts
|
(C++26)
|
teilt ein einzelnes datenparalleles Objekt in mehrere auf
(Funktions-Template) |
|
(C++26)
|
verkettet mehrere datenparallele Objekte zu einem einzelnen
(Funktions-Template) |
Algorithmen
Elementweise Min/Max-Operationen für
basic_simd
(Funktionstemplate) |
|
|
(C++26)
|
Elementweise Clamp-Operation für
basic_simd
(Funktionstemplate) |
|
(C++26)
|
Elementweise Selektion mittels Konditionaloperator
(Funktionstemplate) |
Reduktionen
reduziert alle Werte in
basic_simd
über eine spezifizierte binäre Operation auf einen einzelnen Wert
(Funktionstemplate) |
|
Reduktionen von
basic_simd_mask
zu
bool
(Funktionstemplate) |
|
|
(C++26)
|
Reduktion von
basic_simd_mask
zur Anzahl der
true
Werte
(Funktionstemplate) |
Reduktionen von
basic_simd_mask
zum Index des ersten oder letzten
true
Wertes
(Funktionstemplate) |
Traits
|
(C++26)
|
ermittelt eine geeignete Ausrichtung für
datapar::flag_aligned
(Klassentemplate) |
|
(C++26)
|
ändert den Elementtyp des datenparallelen Typs
(Klassentemplate) |
|
(C++26)
|
ändert die Breite des datenparallelen Typs
(Klassentemplate) |
Mathematische Funktionen
Alle Funktionen in
<cmath>
und
<complex>
sind überladen für
basic_simd
.
|
Dieser Abschnitt ist unvollständig
Grund: Beschreibung |
Bitmanipulationsfunktionen
Alle Bitmanipulationsfunktionen in
<bit>
sind überladen für
basic_simd
.
|
Dieser Abschnitt ist unvollständig
Grund: Beschreibung |
Implementierungsdetails
ABI-Tags
Die datenparallelen Typen
basic_simd
und
basic_simd_mask
sind mit
ABI-Tags
assoziiert. Diese Tags sind Typen, die die Größe und binäre Darstellung datenparalleler Objekte spezifizieren. Das Design sieht vor, dass Größe und binäre Darstellung je nach Zielarchitektur und Compiler-Flags variieren. Der ABI-Tag bestimmt zusammen mit dem Elementtyp die Breite.
Der ABI-Tag bleibt unabhängig von der Auswahl des Maschinenbefehlssatzes. Der gewählte Maschinenbefehlssatz begrenzt die verwendbaren ABI-Tag-Typen. Die ABI-Tags ermöglichen es Benutzern, Objekte vom Datentyp data-parallel sicher über Übersetzungseinheitsgrenzen hinweg zu übergeben.
| Dieser Abschnitt ist unvollständig |
Nur zur Darstellung bestimmte Entitäten
|
Dieser Abschnitt ist unvollständig
Grund: muss aktualisiert werden |
|
using
/*simd-size-type*/
=
/* siehe Beschreibung */
;
|
(1) | ( Nur zur Darstellung* ) |
|
template
<
std::
size_t
Bytes
>
using /*integer-from*/ = /* siehe Beschreibung */ ; |
(2) | ( Nur zur Darstellung* ) |
|
template
<
class
T,
class
Abi
>
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* siehe Beschreibung */ ; |
(3) | ( Nur zur Darstellung* ) |
|
template
<
class
T
>
constexpr std:: size_t /*mask-element-size*/ = /* siehe Beschreibung */ ; |
(4) | ( Nur zur Darstellung* ) |
|
template
<
class
T
>
concept /*constexpr-wrapper-like*/ = /* siehe Beschreibung */ ; |
(5) | ( Nur zur Darstellung* ) |
|
template
<
class
T
>
using /*deduced-simd-t*/ = /* siehe Beschreibung */ ; |
(6) | ( Nur zur Darstellung* ) |
|
template
<
class
V,
class
T
>
using /*make-compatible-simd-t*/ = /* siehe Beschreibung */ ; |
(7) | ( Nur zur Darstellung* ) |
T
, sodass
sizeof
(
T
)
gleich
Bytes
ist.
basic_simd<T, Abi>
, oder
0
andernfalls.
T
für
std
::
datapar
::
basic_simd_mask
<
Bytes, Abi
>
steht,
/*mask-element-size*/
<
T
>
entspricht
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
)
, falls der Typ von
x
+
x
eine aktivierte Spezialisierung von
basic_simdist; andernfalls - void .
- /*deduced-simd-t*/ < T > , falls dieser Typ nicht void ist, andernfalls
- std :: datapar :: simd < decltype ( x + x ) , V :: size ( ) > .
|
Anforderungen an mathematische Funktionen
|
||
|
template
<
class
V
>
concept /*simd-floating-point*/ = /* see description */ ; |
(8) | ( Nur zur Darstellung* ) |
|
template
<
class
...
Ts
>
concept /*math-floating-point*/ = /* see description */ ; |
(9) | ( Nur zur Darstellung* ) |
|
template
<
class
...
Ts
>
requires
/*math-floating-point*/
<
Ts...
>
|
(10) | ( Nur zur Darstellung* ) |
|
template
<
class
BinaryOp,
class
T
>
concept /*reduction-binary-operation*/ = /* see description */ ; |
(11) | ( Nur zur Darstellung* ) |
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
für
Ts...
[
0
]
,
T1
für
Ts...
[
1
]
und
TRest
für ein Pack, sodass
T0, T1, TRest...
äquivalent zu
Ts...
ist. Dann ist
/*math-common-simd-t*/
<
Ts...
>
ein Alias, der äquivalent ist zu:
- /*deduced-simd-t*/ < T0 > , falls sizeof... ( Ts ) == 1 true ist
- andernfalls std:: common_type_t < /*deduced-simd-t*/ < T0 > , /*deduced-simd-t*/ < T1 >> , falls sizeof... ( Ts ) == 2 true ist und /*math-floating-point*/ < T0 > && /*math-floating-point*/ < T1 > true ist,
- andernfalls std:: common_type_t < /*deduced-simd-t*/ < T0 > , T1 > , falls sizeof... ( Ts ) == 2 true ist und /*math-floating-point*/ < T0 > true ist,
- andernfalls std:: common_type_t < T0, /*deduced-simd-t*/ < T1 >> , falls sizeof... ( Ts ) == 2 true ist,
- andernfalls std:: common_type_t < /*math-common-simd-t*/ < T0, T1 > , TRest... > , falls /*math-common-simd-t*/ < T0, T1 > ein gültiger Typ ist,
- andernfalls 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 > wird nur dann modelliert, wenn:
-
-
BinaryOpeine binäre elementweise Operation ist, die kommutativ ist, und -
Ein Objekt vom Typ
BinaryOpmit zwei Argumenten vom Typ std :: datapar :: basic_simd < T, Abi > für einen nicht spezifizierten ABI-TagAbiaufrufbar ist und einen std :: datapar :: basic_simd < T, Abi > zurückgibt.
-
|
SIMD-ABI-Tags
|
||
|
template
<
class
T
>
using /*native-abi*/ = /* siehe Beschreibung */ ; |
(12) | ( Nur zur Darstellung* ) |
|
template
<
class
T,
/*simd-size-type*/
N
>
using /*deduce-abi-t*/ = /* siehe Beschreibung */ ; |
(13) | ( Nur zur Darstellung* ) |
- /*simd-size-v*/ < T, /*deduce-abi-t*/ < T, N >> gleich N ist,
- std :: datapar :: basic_simd < T, /*deduce-abi-t*/ < T, N >> eine aktivierte Spezialisierung ist, und
- std :: datapar :: basic_simd_mask < sizeof ( T ) , /*deduce-abi-t*/ < /*integer-from*/ < sizeof ( T ) > , N >> eine aktivierte Spezialisierung ist.
T
ein vektorisierbarer Typ ist und
N
>
0
&&
N
<=
M
true
ist, wobei
M
ein implementierungsdefiniertes Maximum ist, das mindestens
64
beträgt und je nach
T
variieren kann.
|
Lade- und Speicherflags
|
||
|
struct
/*convert-flag*/
;
|
(14) | ( Nur zur Darstellung* ) |
|
struct
/*aligned-flag*/
;
|
(15) | ( Nur zur Darstellung* ) |
|
template
<
std::
size_t
N
>
struct /*overaligned-flag*/ ; |
(16) | ( Nur zur Darstellung* ) |
std::datapar::flags
verwendet. Siehe
Lade- und Speicher-Flags
für ihre entsprechenden Verwendungen.
Hinweise
| Feature-Test Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_simd
|
202411L
|
(C++26) | Datenparallele Typen und Operationen |
__cpp_lib_simd_complex
|
202502L
|
(C++26) |
Unterstützung von verschachtelten komplexen Werten in
std::datapar::simd
|
Beispiel
#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)); }
Ausgabe:
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
Siehe auch
|
Numerische Arrays, Array-Masken und Array-Slices
(Klassen-Template) |
Externe Links
| 1. | Die Implementierung von ISO/IEC TS 19570:2018 Abschnitt 9 "Data-Parallel Types" — github.com |
| 2. |
TS-Implementierung erreichbar für
GCC/libstdc++
(
std::experimental::simd
wird mit GCC-11 ausgeliefert) — gcc.gnu.org
|