Namespaces
Variants

Data-parallel types (SIMD) (since C++26)

From cppreference.net

このライブラリは、データ並列型とそれらの型に対する操作を提供します:利用可能な場合にデータ並列性を明示的に宣言し、データを構造化するためのポータブルな型。例えば、 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

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - C++関連の専門用語(Main classes、Load and store flags、Algorithms、Traitsなど)は原文のまま保持しました - HTMLタグ、属性、クラス名、IDなどは一切変更していません - 番号付けや構造は完全に保持されています - 技術文書としての正確性と専門性を維持しています

メインクラス

データ並列ベクトル型
(クラステンプレート)
その幅を指定できる basic_simd の便利なエイリアステンプレート
(エイリアステンプレート)
要素型が bool のデータ並列型
(クラステンプレート)
その幅を指定できる basic_simd_mask の便利なエイリアステンプレート
(エイリアステンプレート)

ロード・ストアフラグ

データ並列型のためのロードおよびストアフラグ
(クラステンプレート)
ロードおよびストア操作で使用されるデフォルトフラグ
(定数)
ロードおよびストア操作で値保存的でない変換を有効にするフラグ
(定数)
ロード-ストアアドレスのアライメントが指定されたストレージに対して datapar::alignment の値に合致することを示すフラグ
(定数)
ロード-ストアアドレスのアライメントが指定されたストレージに対して指定されたアライメントに合致することを示すフラグ
(変数テンプレート)

ロード・ストア操作

連続範囲から要素を basic_simd にロードする
(関数テンプレート)
basic_simd から要素を連続範囲にストアする
(関数テンプレート)

キャスト

単一のデータ並列オブジェクトを複数のオブジェクトに分割する
(関数テンプレート)
複数のデータ並列オブジェクトを単一のオブジェクトに連結する
(関数テンプレート)

アルゴリズム

basic_simd に対する要素ごとの最小/最大演算
(関数テンプレート)
basic_simd に対する要素ごとのクランプ演算
(関数テンプレート)
条件演算子を使用した要素ごとの選択
(関数テンプレート)

リダクション

basic_simd 内の全値を指定された二項演算で単一の値に縮約する
(関数テンプレート)
basic_simd_mask bool への縮約
(関数テンプレート)
basic_simd_mask true 値の数への縮約
(関数テンプレート)
basic_simd_mask の最初または最後の true 値のインデックスへの縮約
(関数テンプレート)

Traits

datapar::flag_aligned に適切なアライメントを取得する
(クラステンプレート)
データ並列型の要素型を変更する
(クラステンプレート)
データ並列型の幅を変更する
(クラステンプレート)

数学関数

<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) ( 説明専用* )
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 > は以下のいずれかに等しいエイリアスである:
  • decltype ( x + x ) - x + x の型が有効な basic_simd の特殊化である場合
  • void - それ以外の場合
7) x を型 const T のlvalueとする。 /*make-compatible-simd-t*/ < V, T > は以下のいずれかに等しいエイリアスである:
  • /*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... >

using /*math-common-simd-t*/ = /* 説明を参照 */ ;
(10) ( 説明専用* )
template < class BinaryOp, class T >
concept /*reduction-binary-operation*/ = /* 説明を参照 */ ;
(11) ( 説明専用* )
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... > は以下のいずれかに等価なエイリアスである:
  • /*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 >
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 > は以下の場合にのみモデル化される:

  • 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) ( 説明専用* )
12) /*native-abi*/ < T > はABIタグの実装定義エイリアスです。これは効率的な明示的ベクトル化に使用する主要なABIタグです。その結果、 basic_simd < T, /*native-abi*/ < T >> は有効な特殊化となります。
13) /*deduce-abi-t*/ < T, N > は以下のようなABIタグ型を表すエイリアスである:
  • /*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) ( 説明専用* )
14-16) これらのタグ型は std::datapar::flags のテンプレート引数として使用されます。対応する使用方法については ロード・ストアフラグ を参照してください。

注記

機能テスト マクロ 標準 機能
__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