高度なトピック: 異なる種類の反復空間

これまでのサンプルでは、範囲の指定に blocked_range<T> クラスを使用しました。このクラスは多くの状況で役立ちますが、すべての状況で適切であるとは限りません。プログラマーは、インテル® TBB を使用して独自の反復空間オブジェクトを定義できます。オブジェクトには、基本分割コンストラクター、オプションの比例分割コンストラクター (有効にする特性値を指定)、2 つのプレディケート・メソッドを使用して、サブ空間にオブジェクトを分割する方法を指定する必要があります。クラスを R とすると、メソッドとコンストラクターは次のようになります。

class R {
    // 範囲が空の場合は true
    bool empty() const;
    // 範囲が空でないサブ範囲に分割できる場合は true
    bool is_divisible() const;
    // r をサブ範囲 r と *this に分割
    R( R& r, split );
    // r を比率 p でサブ範囲 r と *this に分割
    R( R& r, proportional_split p );
    // 比例分割コンストラクターの使用を許可
    static const bool is_splittable_in_proportion = true;
    ...
};
    

empty メソッドは、範囲が空の場合に true を返します。is_divisible メソッドは、範囲が空ではない 2 つのサブ範囲に分割された場合に true を返します。この分割はオーバーヘッドが生じてもメリットがあります。基本分割コンストラクターの引数は 2 つ必要です。

第 2 引数は使用されません。この引数は、コンストラクターを通常のコピー・コンストラクターと区別するために用いられます。基本分割コンストラクターは、r をほぼ同じサイズの 2 つに分割し、r を前半として更新して、構築されたオブジェクトを後半とします。

基本分割コンストラクターとは異なり、比例分割コンストラクターはオプションで、tbb::proportional_split 型の第 2 引数を指定します。型には比率の値を返すメソッド left および right が含まれます。これらの値に従って r を分割します。更新された r は比例の左部分に対応し、構築されたオブジェクトは右部分に対応します。比例分割コンストラクターは、スタティック定数 is_splittable_in_proportion がクラスで定義され、値が true の場合にのみ使用されます。

どちらの分割コンストラクターも、更新された r 部分と構築されたオブジェクトが空でないことを保証する必要があります。並列アルゴリズムのテンプレートは、r.is_divisible が true の場合のみ、分割コンストラクターを r 上で呼び出します。

反復空間は、リニアである必要はありません。2 次元の範囲例、tbb/blocked_range2d.h を参照してください。分割コンストラクターは、範囲を最長軸に沿って分割しようとします。parallel_for とともに使用すると、キャッシュの利用効率を高めながら、ループは "再帰的にブロック" されます。このキャッシュの動作は、parallel_forblocked_range2d<T> に対して使用することで、単一プロセッサーでも、同等のシーケンシャル・コードよりもループの実行が速くなることを意味します。

コードサンプル

examples/parallel_for/seismic ディレクトリーには、parallel_forblocked_range をベースとした地震波シミュレーションが含まれています。また、examples/parallel_for/tacheon ディレクトリーには、parallel_forblocked_range2d をベースとした、より複雑なレイ・トレーシングのサンプルが含まれています。