高度なサンプル

より高度な結合操作のサンプルとして、Foo(i) が最小化されたインデックスを求めます。シリアルバージョンは次のとおりです。

long SerialMinIndexFoo( const float a[], size_t n ) {
    float value_of_min = FLT_MAX;        // FLT_MAX from <climits>
    long index_of_min = -1;
    for( size_t i=0; i<n; ++i ) {
        float value = Foo(a[i]);
        if( value<value_of_min ) {
            value_of_min = value;
            index_of_min = i;
        }
    }  
    return index_of_min;
}

求めた最小値とそのインデックスを追跡することでループは動作します。これは、ループの反復間で伝達される唯一の情報です。parallel_reduce を使用してループを変換するには、関数オブジェクトは伝達される情報を追跡して、反復が複数のスレッドに分散された場合にこの情報をマージできなければなりません。また、関数オブジェクトは、コンテキストを提供するため、a へのポインターを記録しなければなりません。

次のコードは、完全な関数オブジェクトです。

class MinIndexFoo {
    const float *const my_a;
public:
    float value_of_min;
    long index_of_min; 
    void operator()( const blocked_range<size_t>& r ) {
        const float *a = my_a;
        for( size_t i=r.begin(); i!=r.end(); ++i ) {
           float value = Foo(a[i]);    
           if( value<value_of_min ) {
               value_of_min = value;
               index_of_min = i;
           }
        }
    }
 
    MinIndexFoo( MinIndexFoo& x, split ) : 
        my_a(x.my_a), 
        value_of_min(FLT_MAX),    // FLT_MAX from <climits>
        index_of_min(-1) 
   {}
 
    void join( const SumFoo& y ) {
        if( y.value_of_min<value_of_min ) {
            value_of_min = y.value_of_min;
            index_of_min = y.index_of_min;
        }
    }
             
    MinIndexFoo( const float a[] ) :
        my_a(a), 
        value_of_min(FLT_MAX),    // FLT_MAX from <climits>
        index_of_min(-1),
    {}
};

SerialMinIndex は、次のように parallel_reduce を使用して、記述を変更することができます。

long ParallelMinIndexFoo( float a[], size_t n ) {
    MinIndexFoo mif(a);
    parallel_reduce(blocked_range<size_t>(0,n), mif );
   
return mif.index_of_min; }

examples/parallel_reduce/primes ディレクトリーに、parallel_reduce を利用した素数検索のサンプルが含まれています。