找到组元素推力然后找到平均值

时间:2016-07-19 03:30:25

标签: vector cuda thrust

我有四个这样的载体

d_xx[0]= 0.75   d_yy[0]= 0.75   d_vx[0]= 1.05488    d_vy[0]= 0.0427136
d_xx[1]= 0.25   d_yy[1]= 0.75   d_vx[1]= 2.03481    d_vy[1]= -0.757107
d_xx[2]= 0.75   d_yy[2]= 0.25   d_vx[2]= 0.234851   d_vy[2]= 1.63537
d_xx[3]= 0.25   d_yy[3]= 0.25   d_vx[3]= -0.442835  d_vy[3]= -0.00224912
d_xx[4]= 1.75   d_yy[4]= 0.75   d_vx[4]= 1.86096    d_vy[4]= -0.822878
d_xx[5]= 1.25   d_yy[5]= 0.75   d_vx[5]= -1.52816   d_vy[5]= -1.94596
...

如何在xx_low = 0xx_high = 1yy_low = 0yy_high = 1之间找到给定范围内的元素,然后我想查找列d_vx[N]的平均值和d_vy[N]使用推力。

最好的方法是怎样做的?我必须先把它排序吗?

1 个答案:

答案 0 :(得分:3)

我可以想到至少3种可能的实现:

  1. sort个元素,find_if满足范围标准的最后一个元素,然后是reduce
  2. copy_if将满足范围标准的所有元素转换为新的向量,然后reduce
  3. transform_reduce带有自定义仿函数,可以使元素无法落入所需范围。
  4. 以下代码实现了第三个想法:

    #include <thrust/device_vector.h>
    #include <thrust/iterator/zip_iterator.h>
    #include <thrust/transform_reduce.h>
    #include <thrust/tuple.h>
    #include <iostream>
    
    template <typename T>
    struct nullify
    {
      T xx_low;
      T xx_high;
      T yy_low;
      T yy_high;
    
      nullify(T xx_low, T xx_high, T yy_low, T yy_high) : xx_low(xx_low), xx_high(xx_high), yy_low(yy_low), yy_high(yy_high){}
    
      using result_type = thrust::tuple<T,T,std::size_t>;
    
      template <typename Tuple>
      __host__ __device__
      result_type operator()(const Tuple& t)
      {
        const T& xx = thrust::get<0>(t);
        const T& yy = thrust::get<1>(t);
    
        return (xx >= xx_low && xx <= xx_high && yy >= yy_low && yy <= yy_high) ? thrust::make_tuple(thrust::get<2>(t), thrust::get<3>(t), 1) : thrust::make_tuple(T(0),T(0),0);
      }
    };
    
    struct tuple_plus
    {
        template <typename Tuple>
        __host__ __device__
        Tuple operator()(const Tuple& lhs, const Tuple& rhs)
        {
            return thrust::make_tuple(thrust::get<0>(lhs) + thrust::get<0>(rhs),
                                      thrust::get<1>(lhs) + thrust::get<1>(rhs),
                                      thrust::get<2>(lhs) + thrust::get<2>(rhs));
        }
    };
    
    
    int main()
    {
        using T = float;
        thrust::device_vector<T> d_xx(6);
        thrust::device_vector<T> d_yy(6);
        thrust::device_vector<T> d_vx(6);
        thrust::device_vector<T> d_vy(6);
        d_xx[0]= 0.75; d_yy[0]= 0.75; d_vx[0]= 1.05488;   d_vy[0]= 0.0427136;
        d_xx[1]= 0.25; d_yy[1]= 0.75; d_vx[1]= 2.03481;   d_vy[1]= -0.757107;
        d_xx[2]= 0.75; d_yy[2]= 0.25; d_vx[2]= 0.234851;  d_vy[2]= 1.63537;
        d_xx[3]= 0.25; d_yy[3]= 0.25; d_vx[3]= -0.442835; d_vy[3]= -0.00224912;
        d_xx[4]= 1.75; d_yy[4]= 0.75; d_vx[4]= 1.86096;   d_vy[4]= -0.822878;
        d_xx[5]= 1.25; d_yy[5]= 0.75; d_vx[5]= -1.52816;  d_vy[5]= -1.94596;
    
        T xx_low  = 0;
        T xx_high = 1;
        T yy_low  = 0;
        T yy_high = 1; 
    
        auto zip_begin = thrust::make_zip_iterator(thrust::make_tuple(d_xx.begin(), d_yy.begin(), d_vx.begin(), d_vy.begin()));
        auto zip_end = thrust::make_zip_iterator(thrust::make_tuple(d_xx.end(), d_yy.end(), d_vx.end(), d_vy.end()));
    
        using Functor = nullify<T>;
        using ResultTuple = typename Functor::result_type;
        ResultTuple result = thrust::transform_reduce(zip_begin, zip_end, nullify<T>(xx_low, xx_high, yy_low, yy_high), thrust::make_tuple(T(0), T(0), 0), tuple_plus());
    
        T avg_d_vx = thrust::get<0>(result) / thrust::get<2>(result);
        T avg_d_vy = thrust::get<1>(result) / thrust::get<2>(result);
        std::cout << "avg_d_vx=" << avg_d_vx << " avg_d_vy=" << avg_d_vy << std::endl;
    }
    

    <强>输出

    avg_d_vx=0.720426 avg_d_vy=0.229682