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

find group element thrust then find average

我有四个这样的向量

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 之间找到给定范围内的元素,然后我想找到列 [=15] 的平均值=] 和 d_vy[N] 使用推力。

最好的方法是什么?我必须先排序吗?

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

  1. sort个元素,find_if最后一个满足范围条件的元素,然后reduce
  2. copy_if所有满足范围条件的元素到一个新的向量中,然后,然后reduce
  3. transform_reduce 带有自定义函子,可以使不在所需范围内的元素无效。

下面的代码实现了第三个思路:

#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