Data-parallel types (SIMD) (since C++26)
このライブラリは、データ並列型とそれらの型に対する操作を提供します:利用可能な場合にデータ並列性を明示的に宣言し、データを構造化するためのポータブルな型。例えば、 SIMD レジスタや命令、または共通の命令デコーダによって駆動される実行ユニットなど、データ並列実行リソースを通じて実現されます。
vectorizable types のセットは以下で構成されます:
- すべての標準整数型および文字型;
- ほとんどの浮動小数点型( float 、 double 、および選択された拡張浮動小数点型: std:: float16_t 、 std:: float32_t 、 std:: float64_t が定義されている場合)を含む; および
-
std::
complex
<
T
>
(
Tがベクトル化可能な浮動小数点型である場合)。
データ並列型 は、ベクトル化可能な基本型( 要素型 と呼ばれる)の1つ以上の要素で構成されます。要素の数( 幅 と呼ばれる)は、各データ並列型に対して一定です。
データ並列型は、クラステンプレート
basic_simd
および
basic_simd_mask
のすべての有効な特殊化を指します。
データ並列型の
data-parallel object
は、型
T
のオブジェクトと同様に動作します。ただし、
T
が単一の値を格納および操作するのに対し、要素型
T
を持つデータ並列型は複数の値を格納および操作します。
データ並列オブジェクトに対するすべての操作は、 要素ごと に作用します(リダクションなどの水平操作を除く。これらはそのように明確にマークされています)。各操作はオブジェクトの各要素、または2つのオブジェクトの対応する要素に適用されます。このような各適用は、他の適用に対して順序付けられていません。この単純な規則はデータ並列性を表現し、コンパイラによってSIMD命令および/または独立した実行ストリームを生成するために使用されます。
データ並列オブジェクトに対するすべての操作(非 constexpr 数学関数オーバーロードを除く)は constexpr です:定数式の評価においてデータ並列オブジェクトを作成し使用することが可能です。
エイリアステンプレート
simd
および
simd_mask
は、ユーザーが特定のサイズに幅を指定できるように定義されています。デフォルトの幅は、コンパイル時に実装によって決定されます。
|
定義済みヘッダー
<simd>
|
|
|
定義済み名前空間
std::datapar
|
目次 |
メインクラス
|
(C++26)
|
データ並列ベクトル型
(クラステンプレート) |
|
(C++26)
|
その幅を指定できる
basic_simd
の便利なエイリアステンプレート
(エイリアステンプレート) |
|
(C++26)
|
要素型が
bool
のデータ並列型
(クラステンプレート) |
|
(C++26)
|
その幅を指定できる
basic_simd_mask
の便利なエイリアステンプレート
(エイリアステンプレート) |
ロード・ストアフラグ
|
(C++26)
|
データ並列型のためのロードおよびストアフラグ
(クラステンプレート) |
|
(C++26)
|
ロードおよびストア操作で使用されるデフォルトフラグ
(定数) |
|
(C++26)
|
ロードおよびストア操作で値保存的でない変換を有効にするフラグ
(定数) |
|
(C++26)
|
ロード-ストアアドレスのアライメントが指定されたストレージに対して
datapar::alignment
の値に合致することを示すフラグ
(定数) |
|
(C++26)
|
ロード-ストアアドレスのアライメントが指定されたストレージに対して指定されたアライメントに合致することを示すフラグ
(変数テンプレート) |
ロード・ストア操作
連続範囲から要素を
basic_simd
にロードする
(関数テンプレート) |
|
basic_simd
から要素を連続範囲にストアする
(関数テンプレート) |
キャスト
|
(C++26)
|
単一のデータ並列オブジェクトを複数のオブジェクトに分割する
(関数テンプレート) |
|
(C++26)
|
複数のデータ並列オブジェクトを単一のオブジェクトに連結する
(関数テンプレート) |
アルゴリズム
basic_simd
に対する要素ごとの最小/最大演算
(関数テンプレート) |
|
|
(C++26)
|
basic_simd
に対する要素ごとのクランプ演算
(関数テンプレート) |
|
(C++26)
|
条件演算子を使用した要素ごとの選択
(関数テンプレート) |
リダクション
basic_simd
内の全値を指定された二項演算で単一の値に縮約する
(関数テンプレート) |
|
basic_simd_mask
の
bool
への縮約
(関数テンプレート) |
|
|
(C++26)
|
basic_simd_mask
の
true
値の数への縮約
(関数テンプレート) |
basic_simd_mask
の最初または最後の
true
値のインデックスへの縮約
(関数テンプレート) |
Traits
|
(C++26)
|
datapar::flag_aligned
に適切なアライメントを取得する
(クラステンプレート) |
|
(C++26)
|
データ並列型の要素型を変更する
(クラステンプレート) |
|
(C++26)
|
データ並列型の幅を変更する
(クラステンプレート) |
数学関数
<cmath>
および
<complex>
内のすべての関数は
basic_simd
に対してオーバーロードされています。
|
このセクションは不完全です
理由: 説明 |
ビット操作関数
<bit>
内のすべてのビット操作関数は
basic_simd
に対してオーバーロードされています。
|
このセクションは不完全です
理由: 説明 |
実装詳細
ABIタグ
データ並列型
basic_simd
および
basic_simd_mask
は
ABIタグ
と関連付けられています。これらのタグは、データ並列オブジェクトのサイズとバイナリ表現を指定する型です。この設計は、ターゲットアーキテクチャとコンパイラフラグに基づいてサイズとバイナリ表現が変化することを意図しています。ABIタグは、要素型と共に幅を決定します。
ABIタグは、マシン命令セットの選択とは独立して残ります。選択されたマシン命令セットは、使用可能なABIタグのタイプを制限します。ABIタグにより、ユーザーはデータ並列型のオブジェクトを翻訳単位の境界を越えて安全に受け渡すことができます。
| このセクションは不完全です |
説明専用エンティティ
|
このセクションは不完全です
理由:更新が必要 |
|
using
/*simd-size-type*/
=
/* see description */
;
|
(1) | ( 説明専用* ) |
|
template
<
std::
size_t
Bytes
>
using /*integer-from*/ = /* see description */ ; |
(2) | ( 説明専用* ) |
|
template
<
class
T,
class
Abi
>
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* see description */ ; |
(3) | ( 説明専用* ) |
|
template
<
class
T
>
constexpr std:: size_t /*mask-element-size*/ = /* see description */ ; |
(4) | ( 説明専用* ) |
|
template
<
class
T
>
concept /*constexpr-wrapper-like*/ = /* see description */ ; |
(5) | ( 説明専用* ) |
|
template
<
class
T
>
using /*deduced-simd-t*/ = /* see description */ ; |
(6) | ( 説明専用* ) |
|
template
<
class
V,
class
T
>
using /*make-compatible-simd-t*/ = /* see description */ ; |
(7) | ( 説明専用* ) |
T
のエイリアスであり、
sizeof
(
T
)
が
Bytes
と等しいことを満たす。
basic_simd<T, Abi>
の幅を示し、それ以外の場合は
0
となります。
T
が
std
::
datapar
::
basic_simd_mask
<
Bytes, Abi
>
を表す場合、
/*mask-element-size*/
<
T
>
は
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
)
-
x
+
x
の型が有効な
basic_simdの特殊化である場合 - void - それ以外の場合
- /*deduced-simd-t*/ < T > (この型が void でない場合)、さもなければ
- std :: datapar :: simd < decltype ( x + x ) , V :: size ( ) > 。
|
数学関数の要件
|
||
|
template
<
class
V
>
concept /*simd-floating-point*/ = /* 説明を参照 */ ; |
(8) | ( 説明専用* ) |
|
template
<
class
...
Ts
>
concept /*math-floating-point*/ = /* 説明を参照 */ ; |
(9) | ( 説明専用* ) |
|
template
<
class
...
Ts
>
requires
/*math-floating-point*/
<
Ts...
>
|
(10) | ( 説明専用* ) |
|
template
<
class
BinaryOp,
class
T
>
concept /*reduction-binary-operation*/ = /* 説明を参照 */ ; |
(11) | ( 説明専用* ) |
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
を
Ts...
[
0
]
とし、
T1
を
Ts...
[
1
]
とし、
TRest
を
T0, T1, TRest...
が
Ts...
と等価となるようなパックとする。このとき、
/*math-common-simd-t*/
<
Ts...
>
は以下のいずれかに等価なエイリアスである:
- /*deduced-simd-t*/ < T0 > 、ただし sizeof... ( Ts ) == 1 が true の場合
- それ以外の場合、 std:: common_type_t < /*deduced-simd-t*/ < T0 > , /*deduced-simd-t*/ < T1 >> 、ただし sizeof... ( Ts ) == 2 が true かつ /*math-floating-point*/ < T0 > && /*math-floating-point*/ < T1 > が true の場合
- それ以外の場合、 std:: common_type_t < /*deduced-simd-t*/ < T0 > , T1 > 、ただし sizeof... ( Ts ) == 2 が true かつ /*math-floating-point*/ < T0 > が true の場合
- それ以外の場合、 std:: common_type_t < T0, /*deduced-simd-t*/ < T1 >> 、ただし sizeof... ( Ts ) == 2 が true の場合
- それ以外の場合、 std:: common_type_t < /*math-common-simd-t*/ < T0, T1 > , TRest... > 、ただし /*math-common-simd-t*/ < T0, T1 > が有効な型である場合
- それ以外の場合、 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 > は以下の場合にのみモデル化される:
-
-
BinaryOpが可換な二項要素単位演算であり、 -
BinaryOp型のオブジェクトが、未指定のABIタグAbiに対する std :: datapar :: basic_simd < T, Abi > 型の2つの引数で呼び出し可能であり、 std :: datapar :: basic_simd < T, Abi > を返す場合。
-
|
SIMD ABI タグ
|
||
|
template
<
class
T
>
using /*native-abi*/ = /* 説明を参照 */ ; |
(12) | ( 説明専用* ) |
|
template
<
class
T,
/*simd-size-type*/
N
>
using /*deduce-abi-t*/ = /* 説明を参照 */ ; |
(13) | ( 説明専用* ) |
- /*simd-size-v*/ < T, /*deduce-abi-t*/ < T, N >> が N と等しく、
- std :: datapar :: basic_simd < T, /*deduce-abi-t*/ < T, N >> が有効な特殊化であり、
- std :: datapar :: basic_simd_mask < sizeof ( T ) , /*deduce-abi-t*/ < /*integer-from*/ < sizeof ( T ) > , N >> が有効な特殊化である場合。
T
がベクトル化可能な型であり、かつ
N
>
0
&&
N
<=
M
が
true
である場合にのみ定義される。ここで
M
は実装定義の最大値であり、少なくとも
64
以上であり、
T
に応じて異なる場合がある。
|
ロードおよびストアフラグ
|
||
|
struct
/*convert-flag*/
;
|
(14) | ( 説明専用* ) |
|
struct
/*aligned-flag*/
;
|
(15) | ( 説明専用* ) |
|
template
<
std::
size_t
N
>
struct /*overaligned-flag*/ ; |
(16) | ( 説明専用* ) |
注記
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_simd
|
202411L
|
(C++26) | データ並列型と操作 |
__cpp_lib_simd_complex
|
202502L
|
(C++26) |
std::datapar::simd
におけるインターリーブされた複素数値のサポート
|
例
#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); // オーバーロードされた数学関数は <simd> で定義されている println("cos²(x) + sin²(x)", std::pow(std::cos(x), 2) + std::pow(std::sin(x), 2)); }
出力:
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
関連項目
|
数値配列、配列マスクおよび配列スライス
(クラステンプレート) |
外部リンク
| 1. | ISO/IEC TS 19570:2018 セクション9「データ並列型」の実装 — github.com |
| 2. |
TS実装の到達状況:
GCC/libstdc++
(
std::experimental::simd
はGCC-11で出荷) — gcc.gnu.org
|