2012-02-20 10 views
5

Próbuję obliczyć średnią pewnej tablicy, która zawiera punkty (x, y).
Czy można użyć ciągu, aby znaleźć średni punkt oznaczony jako punkt (x, y)? Mogę również reprezentować tablicę jako thrust::device_vector<int>, gdy każda komórka zawiera bezwzględną pozycję punktu, co oznacza i*numColumns + j, chociaż nie jestem pewien, czy średnia reprezentuje średnią komórkę.
Dzięki! Odpowiedźjak obliczyć średnią z tablicy int2 za pomocą Thrust

+2

nie można po prostu obliczyć zdefiniować operatora dodawania do 'typu int2' (tzn.' A + b = {a.x + bx, a.y + przez} '), a następnie użyć standardu zmniejszenie do obliczenia sumy na wejściu, a następnie podzielenie przez liczbę elementów? – talonmies

+0

Możesz użyć operatora, jeśli używasz symboli zastępczych lambda Thrust 1.5+ (zobacz moją odpowiedź na dodatek poniżej). – harrism

Odpowiedz

8
#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; 
} 
6

Keveman jest prawidłowy, po prostu chcę, aby dodać Przydatna wskazówka, która wymaga kodu, więc będę je umieścić tutaj, a nie w komentarzach.

Thrust 1.5 dodaje symbole zastępcze lambda, dzięki czemu podejście @ keveman staje się jeszcze prostsze. Zamiast funktora, po prostu zdefiniuj operator+ dla int2, a następnie zamień instancję funktora na wyrażenie zastępcze lambda z _1 + _2. Możesz również zastąpić jawną deklarację init dzwoniąc pod numer make_int2() (dostarczony przez CUDA). Uwaga: int2 operator+ jest zdefiniowany w nagłówku CUDA przykładowego zestawu SDK "vector_math.h", ale zdefiniowałem go poniżej, aby było jasne (ponieważ ten plik nie jest standardową częścią 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; 
}