再帰的に分割可能な 2 次元の半開区間を表すテンプレート・クラス。
#include "tbb/blocked_range2d.h"
template<typename RowValue, typename ColValue> class blocked_range2d;
blocked_range2d<RowValue ,ColValue > は、2 次元の半開区間 [i0,j0)×[i1,j1) を表します。範囲の各軸には独自の分割しきい値があります。RowValue および ColValue は、「blocked_range テンプレート・クラス」セクションの表の要件を満たしていなければなりません。いずれかの軸が分割可能な場合、blocked_range2d は分割可能です。blocked_range2d は、Range コンセプトをモデル化します。
namespace tbb { template<typename RowValue, typename ColValue=RowValue> class blocked_range2d { public: // 型 typedef blocked_range<RowValue> row_range_type; typedef blocked_range<ColValue> col_range_type; // コンストラクター blocked_range2d( RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize); blocked_range2d( RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end); // 分割コンストラクター blocked_range2d( blocked_range2d& r, split ); blocked_range2d( blocked_range2d& r, proportional_split proportion ); // 比例分割が可能 static const bool is_splittable_in_proportion = true; // キャパシティー bool empty() const; // アクセス bool is_divisible() const; const row_range_type& rows() const; const col_range_type& cols() const; }; }
次のコードは、シリアル行列乗算と、blocked_range2d を使用して反復空間を指定する、対応する並列行列乗算を示しています。
const size_t L = 150; const size_t M = 225; const size_t N = 300; void SerialMatrixMultiply( float c[M][N], float a[M][L], float b[L][N] ) { for( size_t i=0; i<M; ++i ) { for( size_t j=0; j<N; ++j ) { float sum = 0; for( size_t k=0; k<L; ++k ) sum += a[i][k]*b[k][j]; c[i][j] = sum; } } }
#include "tbb/parallel_for.h" #include "tbb/blocked_range2d.h" using namespace tbb; const size_t L = 150; const size_t M = 225; const size_t N = 300; class MatrixMultiplyBody2D { float (*my_a)[L]; float (*my_b)[N]; float (*my_c)[N]; public: void operator()( const blocked_range2d<size_t>& r ) const { float (*a)[L] = my_a; float (*b)[N] = my_b; float (*c)[N] = my_c; for( size_t i=r.rows().begin(); i!=r.rows().end(); ++i ){ for( size_t j=r.cols().begin(); j!=r.cols().end(); ++j ) { float sum = 0; for( size_t k=0; k<L; ++k ) sum += a[i][k]*b[k][j]; c[i][j] = sum; } } } MatrixMultiplyBody2D( float c[M][N], float a[M][L], float b[L][N] ) : my_a(a), my_b(b), my_c(c) {} }; void ParallelMatrixMultiply(float c[M][N], float a[M][L], float b[L][N]){ parallel_for( blocked_range2d<size_t>(0, M, 16, 0, N, 32), MatrixMultiplyBody2D(c,a,b) ); }
blocked_range2d は、シリアルバージョンの 2 つの最外ループを並列ループにします。parallel_for は、断片が 16x32 になるまで blocked_range2d を再帰的に分割して、各断片で MatrixMultiplyBody2D::operator() を呼び出します。
メンバー | 説明 |
---|---|
row_range_type |
blocked_range<RowValue>。つまり、行の値の型です。 |
col_range_type |
blocked_range<ColValue>。つまり、列の値の型です。 |
blocked_range2d<RowValue,ColValue>( RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize ) |
効果: 値の 2 次元空間を表す blocked_range2d を構築します。空間は、行と列が指定された粒度の、半開直積 [row_begin, row_end) x [col_begin, col_end) です。 例: "blocked_range2d<char,int> r(’a’, ’z’+1, 3, 0, 10, 2);" 文は、形式 (i, j) のすべての値ペアを含む 2 次元の空間を構築します。ここで、i の範囲は 'a' から 'z' で粒度 3、j の範囲は 0 から 9 で粒度 2 です。 |
blocked_range2d<RowValue,ColValue>( RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end ) | blocked_range2d(row_begin,row_end,1,col_begin,col_end,1) と同じ。 |
blocked_range2d<RowValue,ColValue> ( blocked_range2d& range, split ) |
基本分割コンストラクター。 要件: is_divisible() が true であること。 効果: range を 2 つのサブ範囲に分割します。新しく構築される blocked_range2d は、ほぼオリジナルの range の半分で、range は残りになるように更新されます。各サブ範囲の粒度はオリジナルの range の粒度と同じです。分割は行または列単位で行われます。範囲は選択した軸で分割され、分割が繰り返された後、サブ範囲の行と列はそれぞれの粒度の比率になります。例えば、row_grainsize が col_grainsize の 2 倍の場合、サブ範囲は列の 2 倍の行を持つようになります。 |
blocked_range2d<RowValue,ColValue> ( blocked_range2d& range, proportional_split proportion ) |
比例分割コンストラクター。 要件: is_divisible() が true であること。 効果: range を軸の 1 つで指定された proportion の 2 つのサブ範囲に分割します。分割する軸の選択は、基本分割コンストラクターと同じ方法で行われ、選択した軸に比例分割が行われます。2 番目の軸と各サブ範囲の粒度はオリジナルの range と同じです。 |
bool empty() const |
効果: 範囲が空かどうかを決定します。 戻り値: rows().empty()||cols().empty() |
bool is_divisible() const |
効果: 範囲がサブ範囲に分割できるかどうかを決定します。 戻り値: rows().is_divisible()||cols().is_divisible() |
const row_range_type& rows() const |
戻り値: 値の空間の行を含む範囲。 |
const col_range_type& cols() const |
戻り値: 値の空間の列を含む範囲。 |