この記事は、インテルの The Parallel Universe Magazine 24 号に収録されている、インテル® SIMD Data Layout Template (インテル® SDLT) に関する章を抜粋翻訳したものです。
インテルでは、コードの hotspot を特定したり (インテル® VTune™ Amplifier XE など)、コードの最適化についてのアドバイスを表示する (インテル® Advisor XE など) さまざまなツールを提供しています。インテル® C++ コンパイラーは、特定の C++ ループの最適化が成功したかどうかを知らせる詳細な最適化レポートを生成します。1 このたび、インテルは、インテル® Parallel Studio XE やインテル® System Studio のコンポーネントであるインテル® C++ コンパイラーに新しいテンプレート・ライブラリーを追加しました。C++ を使用しているアプリケーション開発者なら、メモリーアクセスのレイアウトを手動で最適化することがいかに大変であるかご存じでしょう。インテル® SIMD Data Layout Template (インテル® SDLT) ライブラリーは、プログラマーが最小の労力/オーバーヘッドで構造体配列 (AoS) 表現から配列構造体 (SoA) 表現に変更できるようにして C++ コードを最適化します。SOA 表現は、メモリー使用量を抑え、データ構造レイアウトの変換を避けてベクトル化を容易にします。
最新のインテル® プロセッサーやコプロセッサーは、ベクトル命令に対応しており、SIMD (Single Instruction Multiple Data) プログラミング・モデルをサポートしています。インテル® アドバンスト・ベクトル・エクステンション 512 (インテル® AVX-512) 命令では、ベクトル化されたコードの浮動小数点演算のピーク・パフォーマンスは、ベクトル化されていないコードの 8 倍 (倍精度) または 16 倍 (単精度) になります。残念ながら、特にベクトル化を考慮しないで書かれたレガシーコードでは、理論性能の限界に達することはまずありません。データのメモリーレイアウトを適切に行わなければ、多くのパフォーマンスは引き出せないままです。
C++ では、データのメモリーレイアウトが、効率的なベクトル化を達成できるかどうかを左右します。構造体および配列を扱う場合は特に重要です。開発者が 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; }
そのようなデータレイアウトは C++ プログラマーにとって当たり前の表現かもしれませんが、この AOS データセットをベクトルレジスターにロードするオーバーヘッドはベクトル化のパフォーマンス・ゲインを相殺してしまいます。AOS 表現よりも SOA 表現のほうがベクトル化に適していますが、C++ プログラマーの直観には反しています。
続きはこちら (PDF) からご覧いただけます。