2012-05-10 77 views
1

我試圖減少使用推力的值的數組的最小值和最大值,我似乎被卡住了。給定一組浮點數,我希望一次減少它們的最小值和最大值,但是使用推力的減少方法,我會得到所有模板編譯錯誤的母親(或至少阿姨)。推力減少不與非等於輸入/輸出類型

我原來的代碼包含5個數值列表,分佈在2個float4數組中,我想減少,但是我已經將它簡化爲這個簡短的例子。

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.5(由CUDA 4.2.7提供) 我的實際代碼正在使用reduce_by_key,而不僅僅是減少。 我在寫這個問題的時候發現了transform_reduce,但那個沒有考慮到鍵。

+3

二進制運算符函數不能從它的參數類型不同的返回類型。爲什麼你爲此使用'thrust :: reduce'?你不能使用'thrust :: minmax_element'嗎? – talonmies

+3

@gpu:當你爲ArrayFire做插件時,你真的應該透露你在AccelerEyes上工作。 –

+2

@gpu:認爲ArrayFire是免費提供的,這是誤導性的,因爲您不知道問問題的人是否需要跨多個GPU進行分發,或者需要任何其他功能會導致它們超出免費版本的要求。然後,每2個GPU每年的價格是2,500美元。 –

回答

3

由於talonmies筆記,你的降低不會編譯,因爲thrust::reduce預計二元運算符的參數類型相匹配的結果類型,但ReduceMinMax的參數類型是float,而它的結果類型爲float2

thrust::minmax_element直接實現這種操作,但如果需要,你可以改爲實現與thrust::inner_product您減少,從而推廣thrust::reduce

#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); 
}