インテル® C++ コンパイラー 17.0 デベロッパー・ガイドおよびリファレンス

SIMD Data Layout Templates について

SIMD Data Layout Templates (SDLT) は、効率良い SIMD (Single Instruction Multiple Data) ベクトルコードを生成するレイアウトを使用して、POD (Plain Old Data) 型のオブジェクト (データメンバーがポインター/参照や仮想関数を含まない構造体) の配列を表現するコンテナーを提供する、C++11 テンプレート・ライブラリーです。 SDLT は、標準 ISO C++11 コードを使用しており、特別な言語やコンパイラーを必要としません。ただし、インテル® コンパイラーでは、OpenMP* SIMD 拡張、インテル® Cilk™ Plus の SIMD 拡張、pragma ivdep のようなパフォーマンス機能を利用できます。 SDLT は、スケーラブルな SIMD ベクトル・プログラミングを促進するように設計されています。SDLT ライブラリーを使用するには、コンパイラーが効率良い SIMD コードを生成できるように、明示的なベクトル・プログラミング・モデルと SDLT コンテナーを使用して SIMD ループとデータレイアウトを指定します。

ライブラリー・インターフェイスの多くは、インターフェイスが特定の型ではなく型の要件によって定義される、汎用プログラミングを採用しています。 汎用プログラミングの例として、C++ 標準テンプレート・ライブラリー (STL) が挙げられます。 汎用プログラミングは、SDLT の柔軟性と効率を高めます。 汎用インターフェイスは、特定のニーズに合わせてコンポーネントのカスタマイズを可能にします。

SDLT を使用することで、ベクトル化に適した新しいデータ構造でコードを再構築するよりもはるかに簡単に SIMD データレイアウトを指定することができ、同時にパフォーマンスも向上させることができます。

目的

C++ プログラムは、多くの場合、高レベル・オブジェクトとしてアルゴリズムを表現できます。 多くのアルゴリズムには、処理が必要なデータセットがあります。 データセットは POD (Plain Old Data) 型のオブジェクトの配列として表現されることが一般的で、開発者はよく std::vector のような C++ 標準テンプレート・ライブラリーのコンテナーを使用して配列を表現します。 次に例を示します。

struct Point3s 
{
    float x;
    float y;
    float z;
	   // ヘルパーメソッド
};

std::vector<Point3s> inputDataSet(count);
std::vector<Point3s> outputDataSet(count);

for(int i=0; i < count; ++i) {
  Point3s inputElement = inputDataSet[i];
  Point3s result = // inputElement の変換はほかの反復に依存していないため、// オブジェクト・ヘルパー・メソッドを使用してアルゴリズムを高レベルに保つことが可能
  outputDataSet[i] = result;
}

可能な場合、コンパイラーは上記のループのベクトル化を試みます。しかし、構造体配列 (AoS) データセットをベクトルレジスターに読み込むためのオーバーヘッドのほうが、ベクトル化によって得られるパフォーマンス・ゲインを上回ります。 このようなプログラムは、SDLT コンテナーと SIMD フレンドリーな内部メモリーレイアウトの使用に適しています。 SDLT コンテナーは、メモリーレイアウトとオブジェクトのオリジナルの表現との間でプリミティブをインポート/エクスポートできるように、accessor オブジェクトを提供します。 次に例を示します。

SDLT_PRIMITIVE(Point3s, x, y, z)

sdlt::soa1d_container<Point3s> inputDataSet(count);
sdlt::soa1d_container<Point3s> outputDataSet(count);

auto inputData = inputDataSet.const_access();
auto outputData = outputDataSet.access();

#pragma forceinline recursive
#pragma omp simd
for(int i=0; i < count; ++i) {
  Point3s inputElement = inputData[i];
  Point3s result = // inputElement の変換はほかの反復に依存していないため、// オブジェクト・ヘルパー・メソッドを使用してアルゴリズムを高レベルに保つことが可能
  outputData[i] = result;
}

ループ内のローカル変数をループ・インデックスを使用してインポート/エクスポートする場合、コンパイラーのベクトル化機能は SIMD フレンドリーなデータ形式にアクセスし、可能な場合ユニットストライドのロードを実行します。 コンパイラーは、ループ内のローカル・オブジェクトにループの外側からアクセスできないことを証明できる場合、ループ・オブジェクトのプライベート表現を配列構造体 (SoA) に変換して最適化できます。 上記の例では、コンテナーのメモリーレイアウトは配列構造体 (SoA) で、ユニットストライドのロードが生成されます。 コンテナーはアライメントされたメモリーを割り当て、アクセサー・オブジェクトはコンパイラーがコード生成を最適化できるように正しいアライメント情報を知らせます。

このドキュメントは SDLT バージョン 2 に対応しています。本バージョンでは、N 次元コンテナーのサポートが追加されています。

下位互換性

バージョン 2 のパブリック・インターフェイスは、バージョン 1 のインターフェイスと完全な下位互換性があります。

下位互換性には、次のものが含まれます。

この互換性は、内部実装には適用されません。SDLT v1 の内部実装は、v2 での追加部分と一致するように更新されました。そのため、内部インターフェイスに依存するコードの下位互換性は保証されません。

古いインターフェイス

次のインターフェイスは廃止されました。代わりに、表に示す後継インターフェイスを使用してください。

古いインターフェイス 廃止バージョン 後継インターフェイス
sdlt::fixed_offset<>
v2
sdlt::fixed<>
sdlt::aligned_offset<>
v2
sdlt::aligned<>

最適化に関する注意事項

インテル® コンパイラーでは、インテル® マイクロプロセッサーに限定されない最適化に関して、他社製マイクロプロセッサー用に同等の最適化を行えないことがあります。これには、インテル® ストリーミング SIMD 拡張命令 2、インテル® ストリーミング SIMD 拡張命令 3、インテル® ストリーミング SIMD 拡張命令 3 補足命令などの最適化が該当します。インテルは、他社製マイクロプロセッサーに関して、いかなる最適化の利用、機能、または効果も保証いたしません。本製品のマイクロプロセッサー依存の最適化は、インテル® マイクロプロセッサーでの使用を前提としています。インテル® マイクロアーキテクチャーに限定されない最適化のなかにも、インテル® マイクロプロセッサー用のものがあります。この注意事項で言及した命令セットの詳細については、該当する製品のユーザー・リファレンス・ガイドを参照してください。

注意事項の改訂 #20110804