Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to calculate an average from a int2 array using Thrust

I'm trying to calculate the average of a certain array which contains points (x,y).
is it possible to use thrust to find the average point represented as a (x,y) point? i could also represent the array as a thrust::device_vector<int>when each cell contains the absolute position of the point, meaning i*numColumns + j though I'm not sure that the average number represents the average cell.
Thanks!

like image 939
igal k Avatar asked Feb 20 '12 16:02

igal k


2 Answers

#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>

struct add_int2 {
  __device__
  int2 operator()(const int2& a, const int2& b) const {
    int2 r;
    r.x = a.x + b.x;
    r.y = a.y + b.y;
    return r;
  }
};

#define N 20

int main()
{
  thrust::host_vector<int2> a(N);
  for (unsigned i=0; i<N; ++i) {
    a[i].x = i;
    a[i].y = i+1;
  }

  thrust::device_vector<int2> b = a;

  int2 init;
  init.x = init.y = 0;

  int2 ave = thrust::reduce(b.begin(), b.end(), init, add_int2());
  ave.x /= N;
  ave.y /= N;

  std::cout << ave.x << " " << ave.y << std::endl;
  return 0;
}
like image 105
keveman Avatar answered Nov 03 '22 00:11

keveman


Keveman's answer is correct, I just want to add a useful tip which requires code, so I'll put it here rather than in the comments.

Thrust 1.5 adds lambda placeholders, which can make @keveman's approach even simpler. Instead of a functor, just define operator+ for int2, and then replace the instantiation of the functor with the _1 + _2 lambda placeholder expression. You can also replace the explicit declaration of init with a call to make_int2() (provided by CUDA). Note: int2 operator+ is defined in the CUDA code sample SDK's "vector_math.h" header, but I define it below to make it clear (since that file isn't a standard part of CUDA).

#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>

using namespace thrust::placeholders;

__device__
int2 operator+(const int2& a, const int2& b) {
  return make_int2(a.x+b.x, a.y+b.y);
}

#define N 20

int main()
{
  thrust::host_vector<int2> a(N);
  for (unsigned i=0; i<N; ++i) {
    a[i].x = i;
    a[i].y = i+1;
  }

  thrust::device_vector<int2> b = a;

  int2 ave = thrust::reduce(b.begin(), b.end(), make_int2(0, 0), _1 + _2);
  ave.x /= N;
  ave.y /= N;

  std::cout << ave.x << " " << ave.y << std::endl;
  return 0;
}
like image 43
harrism Avatar answered Nov 03 '22 00:11

harrism