blocked_rangeNd テンプレート・クラス

概要

再帰的に分割可能な N 次元の半開区間を表すテンプレート・クラス。blocked_rangeNd を利用するには C++11 のサポートが必要です。

ヘッダー

#define TBB_PREVIEW_BLOCKED_RANGE_ND 1
#include "tbb/blocked_rangeNd.h"

構文

template<typename Value, unsigned int N> class blocked_rangeNd;

説明

blocked_rangeNd<Value, N> は、blocked_range の N 次元拡張です。範囲の各次元は、blocked_range<Value> で表されます。Value は、「blocked_range テンプレート・クラス」セクションの対応する表にある Value コンセプトの要件を満たしていなければなりません。

blocked_rangeNd は、Range コンセプトをモデル化します。blocked_rangeNd は、いずれかの軸が分割可能な場合は分割可能で、いずれかの軸が空の場合は空です。比例分割をサポートします。

メンバー

namespace tbb {

    template<typename Value, unsigned int N>
    class blocked_rangeNd {
    public:
        // 型
        using value_type = Value;

        // コンストラクター
        blocked_rangeNd(const blocked_range<Value>& dim0, ..., const blocked_range<Value>& dimN-1);

        // 分割コンストラクター
        blocked_rangeNd(blocked_rangeNd& r, split proportion);
        blocked_rangeNd(blocked_rangeNd& r, proportional_split proportion);

        // 比例分割を有効にする
        static const bool is_splittable_in_proportion = true;

        // キャパシティー
        static constexpr unsigned int ndims();
        bool empty() const;

        // アクセス
        const tbb::blocked_range<Value>& dim(unsigned int k) const;
        bool is_divisible() const;
    };

}
次の表は、このテンプレート・クラスのメンバーの詳細な情報を提供します。
メンバー 説明
value_type

範囲を構成する任意の N 次元の Value の型です。

blocked_rangeNd<Value, N>(const blocked_range<Value>& dim0, ..., const blocked_range<Value>& dimN-1)

コンストラクターは、各次元を表す N blocked_range<value_type> オブジェクトのみ受け付けます。

効果: 指定された粒度で、N 個の 1 次元の半開区間のデカルト積として blocked_rangeNd を構築します。

[ dim0.begin(), dim0.end() ) x ... x [ dimN-1.begin(), dimN-1.end() )

例: 以下の文について考えてみます。

blocked_rangeNd<std::size_t, 2> r({1, 17}, {3, 284, 5});

および

blocked_rangeNd<std::size_t, 2> r(blocked_range<std::size_t>{1, 17}, blocked_range<std::size_t>{3, 284, 5});

これらの文は、2 つの等価な 2 次元空間を構築します。それぞれには、(i, j) 形式のすべての値のペアが含まれます。ここで、i の範囲は 1 から 16 で粒度 1、j の範囲は 3 から 283 で粒度 5 です。

blocked_rangeNd<Value, N>(blocked_rangeNd& r, split proportion)

基本分割コンストラクター。

要件: is_divisible() が true であること。

効果: 次元の 1 つで r を 2 つのサブ範囲に分割します。分割する軸は、各粒度に対する範囲サイズの最大比率により選択されます。その次元では、新しく構築される blocked_range は、オリジナルの range のほぼ後半であり、range は残りに更新されます。各サブ範囲のほかの次元と粒度は、オリジナルの range と同じです。

blocked_rangeNd<Value, N>(blocked_rangeNd& r, proportional_split proportion)

比例分割コンストラクター。

要件: is_divisible()true であること。

効果: 次元の 1 つで r を指定された比率で 2 つのサブ範囲に分割します。選択された軸の比例分割を除いて、基本分割コンストラクターの動作と効果は同じです。

static const bool is_splittable_in_proportion

blocked_rangeNd のインスタンスが比例分割可能であることを示します。true に設定します。

static constexpr unsigned int ndims()

戻り値: 範囲の次元 N。メソッドは定数式で使用できます。

bool empty() const

効果: 範囲が空かどうかを決定します。

戻り値: 少なくとも 1 つの次元が空の場合は true。そうでない場合は false

const blocked_range<Value>& dim(unsigned int k) const

要件: 0 <= k < N

戻り値: k 番目の次元の blocked_range。次元は、コンストラクター引数の順に 0 から番号が付けられます。

例: 範囲 r の場合、次のように定義します。

blocked_rangeNd<std::size_t, 2> r({1, 17}, {3, 284, 5});

r.dim(0)blocked_range<std::size_t>(1, 17) を返し、r.dim(1)blocked_range<std::size_t>(3, 284, 5) を返します。

bool is_divisible() const

効果: 範囲がサブ範囲に分割できるかどうかを決定します。

戻り値: 少なくとも 1 つの次元が分割可能な場合は true。そうでない場合は false。

サンプル

次のサンプルは、3 次元カーネルを特徴のサブ範囲に適用する、特徴マップのパックに対する 3 次元フィルターを計算します。

convolution3d 関数は、出力セルを反復して、セルの値を kernel3d 関数の結果に設定します。反復を並列に実行するには、tbb::blocked_rangeNd<int, 3> を引数として、tbb::parallel_for を呼び出します。

kernel3d 関数は、特徴マップの値を 3 次元カーネルのスコープで要約します。

#define TBB_PREVIEW_BLOCKED_RANGE_ND 1
#include "tbb/blocked_rangeNd.h"

#include "tbb/parallel_for.h"
#include "tbb/parallel_reduce.h"

template<typename Features>
float kernel3d(const Features& feature_maps, int i, int j, int k,
               int kernel_length, int kernel_width, int kernel_height) {
    float result = 0.f;

    for (int feature_i = i; feature_i < i + kernel_length; ++feature_i)
        for (int feature_j = j; feature_j < j + kernel_width; ++feature_j)
            for (int feature_k = k; feature_k < k + kernel_width; ++feature_k)
                result += feature_maps[feature_i][feature_j][feature_k];

    return result;
}

template<typename Features, typename Output>
void convolution3d(const Features& feature_maps, Output& out,
                   int out_length, int out_width, int out_heigth,
                   int kernel_length, int kernel_width, int kernel_height) {
    using range_t = tbb::blocked_rangeNd<int, 3>;

    tbb::parallel_for(
        range_t({0, out_length}, {0, out_width}, {0, out_heigth}),
        [&](const range_t& out_range) {
            auto out_x = out_range.dim(0);
            auto out_y = out_range.dim(1);
            auto out_z = out_range.dim(2);

            for (int i = out_x.begin(); i < out_x.end(); ++i)
                for (int j = out_y.begin(); j < out_y.end(); ++j)
                    for (int k = out_z.begin(); k < out_z.end(); ++k)
                        out[i][j][k] = kernel3d(feature_maps, i, j, k,
                                                kernel_length, kernel_width, kernel_height);
        }
    );
}