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

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

class R {
    // 範囲が空の場合は true
    bool empty() const;
    // 範囲が空でないサブ範囲に分割できる場合は true
    bool is_divisible() const;
    // r をサブ範囲 r と *this に分割
    R( R& r, split );
    ...
};

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

2 番目の引数は使用されません。この引数は、コンストラクターを通常のコピー・コンストラクターと区別するために用いられます。 分割コンストラクターは、r をほぼ同じサイズの 2 つに分割し、r を前半として更新して、構築されたオブジェクトを後半とします。 この 2 つは空であってはなりません。並列アルゴリズムのテンプレートは、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 をベースとした、より複雑なレイ・トレーシングのサンプルが含まれています。