コンピューティングにおいて、構造体の配列 (AoS)、配列の構造体 (SoA)、または配列の構造体の配列 (AoSoA)は、インターリーブに関してメモリ内のレコードのシーケンスを配置する対照的な方法であり、 SIMDおよびSIMTプログラミングで重要です。
配列の構造
配列の構造( SoA ) は、レコード(またはC プログラミング言語では 'struct')の要素をフィールドごとに 1 つの並列配列に分割するレイアウトです。[1]その目的は、単一のSIMD レジスタで同種のデータをロードでき、広い内部データパス(例: 128 ビット)で転送できるため、ほとんどの命令セットアーキテクチャでパックされたSIMD 命令を使用した操作が容易になることです。レコードの特定の部分だけが必要な場合は、その部分だけを反復処理すればよく、1 つのキャッシュ ラインにより多くのデータを収めることができます。欠点は、データを走査するときにより多くのキャッシュ ウェイが必要になることと、インデックス アドレス指定が非効率的になることです。
たとえば、配列の構造を使用して 3D 空間に N 個のポイントを格納するには、次のようにします。
構造体ポイントリスト3D {
浮動小数点数x [ N ];
浮動小数点数y [ N ];
浮動小数点z [ N ];
};
構造体pointlist3Dポイント;
float get_point_x ( int i ) { points を返します。x [ i ]; }
構造の配列
構造体の配列( AoS ) は、その逆の (より従来的な) レイアウトであり、異なるフィールドのデータがインターリーブされます。これはより直感的であることが多く、ほとんどのプログラミング言語で直接サポートされています。
たとえば、構造体の配列を使用して 3D 空間に N 個のポイントを格納するには、次のようにします。
構造体ポイント3D {
浮動小数点数x ;
浮動小数点y ;
浮動小数点z ;
};
構造体 point3Dポイント[ N ];
float get_point_x ( int i ) { points [ i ].xを返します; }
配列の構造の配列
配列の構造体の配列( AoSoA ) または構造体のタイル配列は、以前のレイアウトのハイブリッド アプローチであり、異なるフィールドのデータが SIMD ベクトル サイズに等しいサイズのタイルまたはブロックを使用してインターリーブされます。これは直感的ではないことが多いですが、SoA アプローチのメモリ スループットを実現しながら、最新のプロセッサのキャッシュ ローカリティとロード ポート アーキテクチャとの親和性を高めることができます。[2]特に、最新のプロセッサのメモリ要求は固定幅 (たとえば、キャッシュラインのサイズ[3] ) で満たす必要があります。AoSoA のタイル ストレージは、メモリ アクセス パターンを要求の固定幅に揃えるため、メモリ要求を完了するためのアクセス操作が少なくなり、効率が向上します。[4]
たとえば、SIMD レジスタ幅が 8 浮動小数点 (または 8×32 = 256 ビット) の配列構造体の配列を使用して、3D 空間に N 個のポイントを格納するには、次のようにします。
構造体ポイント3Dx8 {
浮動小数点数x [ 8 ];
フロートy [ 8 ];
浮動小数点z [ 8 ];
};
構造体point3Dx8ポイント[( N + 7 ) / 8 ];
float get_point_x ( int i ) { points [ i / 8 ]を返します。x [ i % 8 ]; }
実際の SIMD レジスタの幅に応じて、異なる幅が必要になる場合があります。内部配列は、そのようなサポートを備えた言語などの SIMD 型に置き換えられる場合がありますfloat32x8。
代替案
構造体のサブセット (個々のフィールドではなく) を並列配列に分割することが可能です。これにより、プログラム内の異なる時点で異なるフィールド部分を使用する場合に、参照の局所性が 実際に向上します(データ指向設計を参照)。
一部のSIMDアーキテクチャでは、SoA 形式から同種のデータをロードするためのストライド ロード/ストア命令が提供されています。一部のCellライブラリで使用されるもう 1 つのオプションは、ソースをレジスタにロードするときに AoS 形式からデータをデインターリーブし、結果を書き出すときにインターリーブすることです (これは、permutesのスーパースカラー問題によって促進されます)。一部のベクトル数学ライブラリは、浮動小数点4D ベクトルを SIMD レジスタに揃えて、関連するデータ パスと命令を活用しながら、プログラマーの利便性も提供しますが、これは 4 レーンより広い SIMD ユニットには拡張できません。
4D ベクトル
AoSとSoAは、4レーンSIMDハードウェアを搭載したマシンで3Dまたは4Dベクターデータを検討する場合に選択肢となります。SIMD ISAは通常、同種データ用に設計されていますが、ドット積命令[5]と追加の並べ替えを提供するものもあり、AoSの場合の処理が容易になります。
ほとんどのGPUハードウェアは4D命令からスカラーSIMTパイプラインに移行していますが、[6] AoSの代わりにSoAを使用する最新のコンピューティングカーネルは、メモリ結合により優れたパフォーマンスを発揮できます。[7]
ソフトウェアサポート
ほとんどの言語は、レコードとさまざまな配列抽象データ型を
組み合わせることで、より自然に AoS 形式をサポートします。
SoA は主に、データ指向設計をサポートするために使用される言語、ライブラリ、またはメタプログラミングツールに見られます。例は次のとおりです。
- R、Pythonの Pandas パッケージ、Juliaの DataFrames.jl パッケージに実装されている「データ フレーム」は、AoS のような SoA にアクセスするためのインターフェイスです。
- Julia パッケージ StructArrays.jl を使用すると、SoA に AoS としてアクセスして、SoA のパフォーマンスと AoS の直感性を組み合わせることができます。
- Datadraw やX マクロ技術を含む C 言語用のコード ジェネレーター。
AoSoAの自動生成はより複雑です。メタプログラミングにおけるAoSoAの例は、 C++で書かれたLANLのCabanaライブラリにあります。デフォルトではベクトル幅が16レーンであると想定されています。[8]
参考文献
- ^ 「データ構造を操作してメモリ使用を最適化する方法」。Intel。2012 年 2 月 9 日。2019年 3 月 17 日閲覧。
- ^ 「メモリレイアウト変換」。Intel。2019年3月26日。 2019年6月2日閲覧。
- ^ 「カーネルプロファイリングガイド」(PDF) . NVIDIA. 2022-12-01 . 2022-01-14に閲覧。)
- ^ フェイ、ユン (レイモンド);ファン、ユハン。 Gao、Ming (2021)、「最新の GPU での物質点法のリアルタイム シミュレーションに向けた原則」、1 ~ 16 ページ、arXiv : 2111.00699 [cs.GR]
- ^ 「Intel SSE4 浮動小数点ドット積組み込み関数」。Intel。2016 年 6 月 24 日時点のオリジナルよりアーカイブ。2019 年 3 月 17 日閲覧。
- ^ 「Modern GPU Architecture (Scalar Unified Pipelines を参照)」(PDF)。NVIDIA。2018年 5 月 17 日のオリジナル(PDF)からアーカイブ。2019年 3 月 17 日に取得。
- ^ Kim, Hyesoon (2010-02-08). 「CUDA 最適化戦略」(PDF) . CS4803 ゲーム コンソールの設計. 2019-03-17に閲覧。
- ^ “ECP-copa/Cabana: AoSoA”. GitHub。
