再帰的に分割可能な 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); } ); }