推力减少不适用于不相等的输入/输出类型 [英] Thrust reduce not working with non equal input/output types

查看:95
本文介绍了推力减少不适用于不相等的输入/输出类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Thrust减少值数组的最小值和最大值,但似乎被卡住了。给定一组浮点数,我想一次减少它们的最小值和最大值,但是使用推力的reduce方法,我改为获取所有模板编译错误的母亲(或至少是阿姨)。



我的原始代码包含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 []){

推力:: device_vector< float>帽子(4);
hat [0] = 3;
hat [1] = 5;
hat [2] = 6;
hat [3] = 1;

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

如果我将其分为2个减少项,那当然可以。然后我的问题是:是否可以通过推力一次减小最小和最大?如何减小?如果不是,那么实现上述减少的最有效方法是什么?转换迭代器会为我提供帮助吗? 1.5(由CUDA 4.2.7提供)
我的实际代码使用的是reduce_by_key,而不仅仅是reduce。
在写此问题时发现了transform_reduce,但是那个没有考虑到键。

解决方案

请注意,您的归约无法编译,因为 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>

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

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

float2 minmax1(const推力:: device_vector< float& x)
{
返回推力:: inner_product(x.begin(),x.end(), x.begin(),make_float2(4.0、4.0f),minmax_float2(),minmax_float());
}

float2 minmax2(const推力:: device_vector< float>& x)
{
使用命名空间推力;
pair< device_vector< float> ::: const_iterator,device_vector< float> :: const_iterator> ptr_to_result;

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

返回make_float2(* ptr_to_result.first,* ptr_to_result.second);
}

int main()
{
推力:: device_vector< float>帽子(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);
}


I'm attempting to reduce the min and max of an array of values using Thrust and I seem to be stuck. Given an array of floats what I would like is to reduce their min and max values in one pass, but using thrust's reduce method I instead get the mother (or at least auntie) of all template compile errors.

My original code contains 5 lists of values spread over 2 float4 arrays that I want reduced, but I've boiled it down to this short example.

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

If I split it into 2 reductions instead it of course works. My question is then: Is it possible to reduce both the min and max in one pass with thrust and how? If not then what is the most efficient way of achieving said reduction? Will a transform iterator help me (and if so, will the reduction then be a one pass reduction?)

Some additional info: I'm using Thrust 1.5 (as supplied by CUDA 4.2.7) My actual code is using reduce_by_key, not just reduce. I found transform_reduce while writing this question, but that one doesn't take keys into account.

解决方案

As talonmies notes, your reduction does not compile because thrust::reduce expects the binary operator's argument types to match its result type, but ReduceMinMax's argument type is float, while its result type is float2.

thrust::minmax_element implements this operation directly, but if necessary you could instead implement your reduction with thrust::inner_product, which generalizes 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);
}

这篇关于推力减少不适用于不相等的输入/输出类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆