Using thrust::copy_if with a parameter

id like to use the copy_if predict, with some parameter. I’ve implemented the predict as a struct, like in the example. i.e a struct with the () operator. I’ve tried defining a static pointer in the same cu file, and allocating to it with cudaMalloc, and then using cuda malloc to copy the parameter value. This doesn’t work because the device operator() inside the predict struct has no access to this pointer.

What is the correct way?

Hi inbaltomer,

Could you clarify the following points?

  1. What kind of parameter are you using? It is a built-in or custom datatype?

In the case of custom datatypes, you will need to define the iterator for using the thrust::copy_if. Basically, behind scenes, the thrust::copy_if will iterate over each element by using the iterator, it will dereference and pass it to your operator() by value. Inside of it, you will take the decision.

So, the proper way is by making sure you have defined the iterator for your datatype.

Regards,
Leon.

Id like to be able to have a parameter inside the operator(). for example, id like to do
*iter > myThreshold;

and be able to set “myThreshold” in some constructor.
My predicate is this for now:

struct isAboveTh
{
	__host__ __device__
		bool operator()(thrust::tuple<pixInd, int> x)
	{
		int v = thrust::get<1>(x);
		return (v > 40000);
	}
	
};

and I’d like to be able to initialize the threshold to some value (not 40000…)

About this, you can use a templated struct. For example:

template<int THRESHOLD>
struct isAboveTh
{
	__host__ __device__
		bool operator()(thrust::tuple<pixInd, int> x)
	{
		int v = thrust::get<1>(x);
		return (v > THRESHOLD);
	}
	
};

From the invocation:

//...
thrust::copy_if(thrust::device, V, V + N, result, isAboveTh<5000>());

Where 500 is your threshold.

Regards,
Leon.

Though of that but that’s only good if i know the value at compile time. my problem is that i calculate the threshold in another function, which is called before the copy_if

Ok. You need something at runtime.

I would do:

struct isAboveTh
{
	__host__ __device__

        int kThreshold;
        explicit isAboveTh(int threshold) : kThreshold{threshold} {}

        bool operator()(thrust::tuple<pixInd, int> x)
	{
		int v = thrust::get<1>(x);
		return (v > kThreshold);
	}
	
};

We can add a member and a constructor to initialise it.

thrust::copy_if(thrust::device, V, V + N, result, isAboveTh{5000});
// or
thrust::copy_if(thrust::device, V, V + N, result, isAboveTh(5000));

In both cases, the () or {} are calling the constructor of the struct

Regards,
Leon

1 Like

Yes! that works! tnx.
So, just to clear for future generations, I was confused by the example of copy_if, which writes:

struct is_even
{
  __host__ __device__
  bool operator()(const int x)
  {
    return (x % 2) == 0;
  }
};
...
const int N = 6;
int V[N] = {-2, 0, -1, 0, 1, 2};
int result[4];
thrust::copy_if(thrust::host, V, V + N, result, is_even());

the use of is_even() confused me as if the operator() is passed to the function , but actually, it is an empty contructor in this case. The constructor can be any constructor, and copy_if calls the object’s operator(). it does not have to be a static class, but an object, with members and all. That way, any predicate, may be used, with as much logic and parameters, as the user needs.

Tnx Leon

2 Likes