コンピューティングにおいて、構造体の配列 (AoS)、配列の構造体 (SoA)、または配列の構造体の配列 (AoSoA)は、インターリーブに関してメモリ内のレコードのシーケンスを配置する対照的な方法であり、 SIMDおよびSIMTプログラミングにおいて関心を集めています。
配列の構造( SoA ) は、レコード( C 言語では「struct」)の要素をフィールドごとに 1 つの並列配列に分割するレイアウトです。[ 1 ]その動機は、ほとんどの命令セット アーキテクチャでパックSIMD 命令による操作が容易になることです。これは、単一のSIMD レジスタで、広い内部データ パス(たとえば128 ビット) を介して転送される可能性のある均質なデータをロードできるためです。レコードの特定の部分だけが必要な場合は、その部分だけを反復処理すればよく、より多くのデータを単一のキャッシュ ラインに収めることができます。欠点は、データを走査する際にキャッシュ ウェイが多く必要になることと、インデックス アドレス指定が非効率的になることです。
例えば、配列の構造を使用して3D空間にN個の点を格納する場合:
struct Vector3List {float x [ N ];float y [ N ];float z [ N ];};struct Vector3List points ;float get_point_x ( size_t i ) {ポイント.x [ i ]を返します。}構造体配列(AoS)は、これとは逆の(より一般的な)レイアウトで、異なるフィールドのデータが交互に配置されます。これは多くの場合、より直感的で、ほとんどのプログラミング言語で直接サポートされています。
例えば、構造体の配列を使用して3D空間にN個の点を格納する場合:
struct Vector3 {float x ;float y ;float z ;};struct Vector3 points [ N ];float get_point_x ( size_t i ) {ポイント[ i ] .xを返す;}配列の構造体の配列( AoSoA ) または構造体のタイル配列は、これまでのレイアウトの中間的なアプローチであり、異なるフィールドのデータは、SIMD ベクトルのサイズと同じサイズのタイルまたはブロックを使用してインターリーブされます。これは直感的ではないことが多いですが、SoA アプローチのメモリ スループットを実現でき、最新のプロセッサのキャッシュ局所性およびロード ポート アーキテクチャにより適しています。[ 2 ]特に、最新のプロセッサでは、メモリ要求は固定幅 (たとえば、キャッシュラインのサイズ[ 3 ] ) で満たされる必要があります。AoSoA のタイル ストレージは、メモリ アクセス パターンを要求の固定幅に合わせるため、メモリ要求を完了するためのアクセス操作が少なくなり、効率が向上します。[ 4 ]
例えば、SIMDレジスタ幅が8浮動小数点数(または8×32=256ビット)の配列構造体の配列を使用して、3D空間にN個の点を格納する場合:
struct Vector3x8 {float x [ 8 ];float y [ 8 ];float z [ 8 ];};struct Vector3x8 points [( N + 7 ) / 8 ];float get_point_x ( size_t i ) {return points [ i / 8 ]. x [ i % 8 ];}実際のSIMDレジスタ幅によっては、異なる幅が必要になる場合があります。内部配列は、float32x8SIMDをサポートする言語の場合、SIMD型に置き換えることができます。
AoSとSoAは、4レーンSIMDハードウェアを備えたマシンで3Dまたは4Dベクトルデータを検討する際の選択肢となります。SIMD ISAは通常、均質なデータ用に設計されていますが、ドット積命令[ 5 ]と追加の順列を提供するものもあり、AoSケースの方が扱いやすくなっています。
ほとんどのGPUハードウェアは4D命令からスカラーSIMTパイプラインに移行しているが、[ 6 ] AoSの代わりにSoAを使用する最新の計算カーネルは、メモリコヒーレンスにより依然として優れたパフォーマンスを発揮できる。[ 7 ]
ほとんどの言語は、レコードとさまざまな配列抽象データ型を 組み合わせることで、AoS形式をより自然にサポートしています。
SoAは主に、データ指向設計をサポートするために使用される言語、ライブラリ、またはメタプログラミングツールに見られます。例としては、次のものが挙げられます。
AoSoAの自動生成はより複雑です。メタプログラミングにおけるAoSoAの例は、LANLのC++で書かれたCabanaライブラリに見られます。これはデフォルトで16レーンのベクトル幅を想定しています。[ 8 ]