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

n_container の構築

説明

N 次元 (多次元) コンテナーは、使用する前に構築する必要があります。最初にデータ型を SDLT_PRIMITIVE として宣言し、データレイアウトを選択して、各次元の範囲を示すことでコンテナーの形状を決定します。

データレイアウトの指定

データレイアウトごとに異なるコンテナーを定義するのではなく、使用するデータレイアウトをコンテナーのテンプレート引数として指定します。

次の表は、利用可能なレイアウトをまとめたものです。詳細は、「n_container」にある表を参照してください。

レイアウト 説明
layout::soa<>
配列構造体 (SoA)。プリミティブの各データメンバーには、個別の N 次元配列があります。
layout::soa_per_row<>
行ごとの配列構造体 (SoA)。プリミティブの各データメンバーには、行ごとに 1 次元の配列があります。残りの N-1 次元についてもこのレイアウトが繰り返されます。
layout::aos_by_struct
構造体によりアクセスされる構造体配列 (AoS)。ネイティブ AoS レイアウトとデータアクセス。
layout::aos_by_stride
ストライドによりアクセスされる構造体配列 (AoS)。メンバーのビルトイン型へのポインターによるストライドを使用したネイティブ SoA アクセス。

数値と定数

形状を定義するため、次の 3 つの形式で整数値を指定できます。ここでは、コンパイラーに提供される情報が多い順に示します。できるだけ厳密な形状を指定してください。情報が多いほうが、コンパイラーは効率良く最適化を行うことができます。

整数値の指定 説明
fixed<int NumberT>
コンパイル時に値が分かっている場合。

foo(fixed<1080>(), fixed<1920>());

サフィックス _fixed は同等のリテラルを宣言します。例えば、1080_fixedfixed<1080> と同等です。

foo(1080_fixed, 1920_fixed);

aligned<int AlignmentT>(number)
プログラマーは、数値が AlignmentT の倍数になるように保証しなければなりません。

foo(aligned<8>(height), aligned<128>(width));

“int”
任意の整数値。

foo(width, height);

コンテナーの形状の指定

n_extent_t<…> は、任意の数の引数を受け付ける可変個引数テンプレートです。この型のコンストラクターは分かりづらいため、配列定義のような構文ですべての次元の範囲を構築できるジェネレーター・オブジェクト n_extent が提供されています。コンパイラーがさらに多くのデータ・アライメントの可能性を証明できるように、上記のように、範囲の値にはできるだけ厳密な範囲を使用します。

n_extent[height][width];                 // OK
n_extent[height][aligned<128>(width)];  // 良い
n_extent[1080_fixed][1920_fixed];       // 最良

n_container の定義

宣言済みのプリミティブを使用します (SDLT v1 と同じ)。

struct RGBAs { float red, green, blue, alpha; };
SDLT_PRIMITIVE(RGBAs, red, green, blue, alpha)

HD イメージサイズ 1920x0180 の RGBAs の 2 次元コンテナーは、次のように宣言し、インスタンス化できます。

typedef n_container<RGBAs, layout::soa, 
                    n_extent_t<fixed<1080>, fixed<1920>>> HdImage;
HdImage image1;

サイズが不明な場合は、範囲を使用してコンテナーを定義できます。範囲は、コンパイル時には不明でも、実行時にコンテナーのインスタンスが作成されると分かります。

typedef n_container<RGBAs, layout::soa, n_extent_t<int, int>> Image;
Image image2(n_extent[height][width]);

また、テンプレート・ファクトリー関数 make_n_container<PrimitiveT, LayoutT> を使用してコンテナーを作成することもできます。

auto image1 = make_n_container<RGBAs, 
                          layout::soa>(n_extent[1080_fixed][1920_fixed]);
auto image2 = make_n_container<RGBAs, 
                           layout::soa>(n_extent[height][width]);

セルへのアクセス

コンテナーがデータを所有しています。コンテナー内のデータを取得するには、「アクセサー」を使用します。

auto ca = image1.const_access();
auto a = image2.access();

C の多次元配列に似た、配列添字演算子 [] への一連の呼び出しにより、各次元のインデックスを指定します。

RGBAs pixel = ca[y][x];
float greyscale = (pixel.red + pixel.green + pixel.blue)/3;
a[y][x] = RGBAs(greyscale, greyscale, greyscale); 

範囲の特定

アクセサーは範囲を把握しています。

テンプレート関数 extent_d<int DimensionT>(object) を使用します。

for (int y = 0; y < extent_d<0>(ca); ++y)
    for (int x = 0; x < extent_d<1>(ca); ++x) {
          RGBAs pixel = ca[y][x];
		 // …
    }

便宜上、非テンプレート・メソッドも提供されています。

for (int y = 0; y < ca.extent_d0(); ++y)
    for (int x = 0; x < ca.extent_d1(); ++x) {
          RGBAs pixel = ca[y][x];
		 // …
    }

次元の引き下げ

アクセサーがすべての次元にアクセスする必要がない場合、次元数の少ない新しいアクセサーによりアクセスすることができます。

auto cay = ca[y];
RGBAs pixel = cay[x];