Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thrust Gathering/Filtering

Tags:

cuda

thrust

What I am trying to do is create a filter on a vector so it removes elements that do not pass a predicate test; but not too sure how I go about it.

I evaluate each element in my inputer vector against the predicate, for example in my code the is_even functor, in a device_vector vector. It is true if it passes the test and false if it's not.

Now I am stuck because I now have this bool vector and I want to gather the elements that passed this predicate test. I store it in a bool vector because I want to keep the result to filter other vectors.

#include ...

template<typename T>
struct is_even : thrust::unary_function<T, bool>
{
    __host__ __device__
    bool operator()(const T &x)
    {
        return (x%2)==0;
    }
};

int main(void)
{
    std::cout << "Loading test!" << std::endl;
    const int N = 1000000;
    thrust::device_vector<int> col1(N);
    thrust::device_vector<float> col2(N, 1); 
    thrust::sequence(col1.begin(), col1.end());

    thrust::device_vector<bool> filter(N);
    thrust::transform(col1.begin(), col1.end(), filter.begin(), is_even<int>());

    // filter col1 and col2 based on filter

    return 0;
}
like image 679
user2991422 Avatar asked Mar 04 '26 23:03

user2991422


1 Answers

Within the stream compaction group you may be interested in thrust::copy_if

We can select the even elements into a new vector directly using your defined predicate without making an intermediate filter vector:

thrust::copy_if(col1.begin(), col1.end(), result.begin(), is_even<int>());

(result should be a vector of identical type to col1, and already defined to be a length equal to or greater than col1, since it's unknown how many elements will pass the predicate test.)

If you want to work off of the filter vector you have created, use the stencil version of copy_if instead.

Here's a worked example using the stencil method based on your comments:

$ cat t267.cu
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/transform.h>
#include <thrust/copy.h>

template<typename T>
struct is_even : thrust::unary_function<T, bool>
{
    __host__ __device__
    bool operator()(const T &x)
    {
        return (x%2)==0;
    }
};


struct is_true : thrust::unary_function<bool, bool>
{
    __host__ __device__
    bool operator()(const bool &x)
    {
        return x;
    }
};

int main(void)
{
    std::cout << "Loading test!" << std::endl;
    const int N = 1000000;
    thrust::device_vector<int> col1(N);
    thrust::device_vector<float> col2(N, 1);
    thrust::sequence(col1.begin(), col1.end());

    thrust::device_vector<bool> filter(N);
    thrust::device_vector<int> result(N);
    thrust::transform(col1.begin(), col1.end(), filter.begin(), is_even<int>());
    // filter col1 based on filter
    thrust::device_vector<int>::iterator end = thrust::copy_if(col1.begin(), col1.end(), filter.begin(), result.begin(), is_true());
    int len = end - result.begin();
    thrust::host_vector<int> h_result(len);
    thrust::copy_n(result.begin(), len, h_result.begin());
    thrust::copy_n(h_result.begin(), 10, std::ostream_iterator<int>(std::cout, "\n"));


    return 0;
}
$ nvcc -arch=sm_20 -o t267 t267.cu
$ ./t267
Loading test!
0
2
4
6
8
10
12
14
16
18
$
like image 139
Robert Crovella Avatar answered Mar 08 '26 00:03

Robert Crovella



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!