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
|
目次
メインクラス
ロード・ストアフラグ
ロード・ストア操作
キャスト
アルゴリズム
リダクション
順列
Traits
数学関数
<cmath>
および
<complex>
内のすべての関数は
ビット操作関数すべてのビット操作関数は<bit>内のstd::bit_castを除いて
実装詳細ABIタグ
データ並列型
ABIタグは、マシン命令セットの選択とは独立して残ります。選択されたマシン命令セットは、使用可能なABIタグのタイプを制限します。ABIタグにより、ユーザーはデータ並列型のオブジェクトを翻訳単位の境界を越えて安全に受け渡すことができます。
説明専用エンティティ
1)
/*simd-size-type*/
は符号付き整数型のエイリアスです。実装は任意の符号付き整数型を選択できます。
2)
/*integer-from*/
<
Bytes
>
は、符号付き整数型
T
のエイリアスであり、
sizeof
(
T
)
が
Bytes
と等しいことを満たす。
3)
/*simd-size-v*/
<
T, Abi
>
は有効な特殊化
basic_simd<T, Abi>
の幅を示し、それ以外の場合は
0
となります。
4)
T
が
std
::
datapar
::
basic_simd_mask
<
Bytes, Abi
>
を表す場合、
/*mask-element-size*/
<
T
>
は
Bytes
と等しい。
5)
コンセプト
/*constexpr-wrapper-like*/
は以下のように定義される:
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;
6)
x
を型
const
T
のlvalueとする。
/*deduced-simd-t*/
<
T
>
は以下のいずれかに等しいエイリアスである:
7)
x
を型
const
T
のlvalueとする。
/*make-compatible-simd-t*/
<
V, T
>
は以下のいずれかに等しいエイリアスである:
8)
コンセプト
/*simd-floating-point*/
は以下のように定義される:
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>;
9)
コンセプト
/*math-floating-point*/
は以下のように定義される:
template< class... Ts > concept /*math-floating-point*/ = (/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);
10)
T0 を
Ts...
[
0
]
とし、
T1 を
Ts...
[
1
]
とし、
TRest を
T0, T1, TRest...
が
Ts...
と等価となるようなパックとする。このとき、
/*math-common-simd-t*/
<
Ts...
>
は以下のいずれかに等価なエイリアスである:
11)
コンセプト
/*reduction-binary-operation*/
は以下のように定義される:
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 > は以下の場合にのみモデル化される:
12)
/*native-abi*/
<
T
>
はABIタグの実装定義エイリアスです。これは効率的な明示的ベクトル化に使用する主要なABIタグです。その結果、
basic_simd
<
T,
/*native-abi*/
<
T
>>
は有効な特殊化となります。
13)
/*deduce-abi-t*/
<
T, N
>
は以下のようなABIタグ型を表すエイリアスである:
T
がベクトル化可能な型であり、かつ
N
>
0
&&
N
<=
M
が
true
である場合にのみ定義される。ここで
M
は実装定義の最大値であり、少なくとも
64
以上であり、
T
に応じて異なる場合がある。
注記
例
このコードを実行
#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 関連項目
|