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;
}
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
$