2012-05-10 12 views
1

推力を使用して値の配列の最小値と最小値を減らそうとしていますが、私はスタックしているようです。浮動小数点数の配列を考えると、1回のパスで最小値と最大値を減らすことができますが、推力のreduceメソッドを使用すると、代わりにすべてのテンプレートコンパイルエラーの母親(または少なくともauntie)を取得します。推力減少が等しくない入力/出力タイプで動作しない

私のオリジナルコードには、2つのfloat4配列に分散された値の5つのリストが含まれていますが、私はこの短い例に煮詰めました。

struct ReduceMinMax { 
    __host__ __device__ 
    float2 operator()(float lhs, float rhs) { 
     return make_float2(Min(lhs, rhs), Max(lhs, rhs)); 
    } 
}; 

int main(int argc, char *argv[]){ 

    thrust::device_vector<float> hat(4); 
    hat[0] = 3; 
    hat[1] = 5; 
    hat[2] = 6; 
    hat[3] = 1; 

    ReduceMinMax binary_op_of_dooooom; 
    thrust::reduce(hat.begin(), hat.end(), 4.0f, binary_op_of_dooooom); 
} 

私はそれを2回に減らしても、それはもちろん動作します。私の質問は次のとおりです。推力と方法で1回のパスで最小と最大の両方を減らすことは可能ですか?もしそうでなければ、その削減を達成する最も効率的な方法は何ですか?変換イテレータ私を助けて(そうであれば、減少が続い1つのパスの削減になりますか?)

いくつかの追加情報になります。(CUDA 4.2.7によって供給されるような)私が使用している は 私の実際のコードを1.5スラスト減らすだけではなく、reduce_by_keyを使用しています。 この質問を書いている間にtransform_reduceが見つかりましたが、キーには考慮されません。

+3

バイナリ演算子関数は引数の型とは異なる戻り値の型を持つことができません。とにかく 'thrust :: reduce'を使っているのはなぜですか? 'thrust :: minmax_element'を使用できませんか? – talonmies

+3

@gpu:ArrayFire用のプラグを使用するたびに、AccelerEyesで作業することを明らかにする必要があります。 –

+2

@gpu:質問をした人が複数のGPUに配布する必要があるのか​​、無料版の要件を超えてしまうような他の機能が必要なのか分からないので、ArrayFireは無料で利用できると誤解しています。次に、価格は2 GPUあたり年間$ 2,500です。 @ RogerDahl Dulyが言及した。 –

答えて

3

talonmiesノートとしてthrust::reduceは、二項演算子の引数の型が、その結果の型と一致することを期待するので、あなたの低下はコンパイルされませんが、その結果の型がfloat2ている間ReduceMinMaxの引数の型は、floatです。

thrust::minmax_element

直接この操作を実装していますが、あなたの代わりに thrust::reduceを一般 thrust::inner_productを使用して減少し、実装することができ、必要に応じて:

#include <thrust/inner_product.h> 
#include <thrust/device_vector.h> 
#include <thrust/extrema.h> 
#include <cassert> 

struct minmax_float 
{ 
    __host__ __device__ 
    float2 operator()(float lhs, float rhs) 
    { 
    return make_float2(thrust::min(lhs, rhs), thrust::max(lhs, rhs)); 
    } 
}; 

struct minmax_float2 
{ 
    __host__ __device__ 
    float2 operator()(float2 lhs, float2 rhs) 
    { 
    return make_float2(thrust::min(lhs.x, rhs.x), thrust::max(lhs.y, rhs.y)); 
    } 
}; 

float2 minmax1(const thrust::device_vector<float> &x) 
{ 
    return thrust::inner_product(x.begin(), x.end(), x.begin(), make_float2(4.0, 4.0f), minmax_float2(), minmax_float()); 
} 

float2 minmax2(const thrust::device_vector<float> &x) 
{ 
    using namespace thrust; 
    pair<device_vector<float>::const_iterator, device_vector<float>::const_iterator> ptr_to_result; 

    ptr_to_result = minmax_element(x.begin(), x.end()); 

    return make_float2(*ptr_to_result.first, *ptr_to_result.second); 
} 

int main() 
{ 
    thrust::device_vector<float> hat(4); 
    hat[0] = 3; 
    hat[1] = 5; 
    hat[2] = 6; 
    hat[3] = 1; 

    float2 result1 = minmax1(hat); 
    float2 result2 = minmax2(hat); 

    assert(result1.x == result2.x); 
    assert(result1.y == result2.y); 
} 
関連する問題