I need a function that computes some "math" function of several variables on GPU. I decided to use Thrust and its zip_iterator
to pack variables in a tuple, and implement my math function as a functor foк for_each
. But I'd like to have a universal function that can compute different "math" functions. So, I need to pass this functor in the function.
As I think, to do this task, I should implement some simple hierarchy (with the only base class) of functors with different versions of operator()(Tuple t)
. For example, functors can be like these:
struct Func {
template <typename Tuple>
__host__ __device__
void operator()(Tuple arg) {
thrust::get<1>(arg) = 0;
}
};
strust f1 : public Func {
...
};
strust f2 : public Func {
...
};
The question is how can I properly pass required functor into the function, and how to define such a function? This function can be like:
thrust::host_vector evaluateFunction(Func func, thrust::host_vector point) {
thrust::host_vector result(point.size());
thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(point.begin(), result.begin())),
thrust::make_zip_iterator(thrust::make_tuple(point.end(), result.end())),
func);
return result;
}
but with such a definition I cannot pass f1
or f2
into it. How can I define it properly?
It appears that you want to pass a user-defined or user-selectable function to thrust, for evaluation in a functor. Based on that, I think a possible answer is very similar to what is posted here, however I'll make some other comments.
thrust::device_vector
would be essentially impossible, because It is not allowed to pass as an argument to a__global__
function an object of a class with virtual functions. Although it's not entirely obvious, this is in effect what I would be doing if I created an appropriate array of objects on the host and then attempted to use them polymorphically in athrust::device_vector
. At least, I could not fight my way through the jungle. You can use polymorphism in device code, of course, assuming the objects are correctly created on the device so that their virtual function tables can be properly assigned. This question and comments may also be of interest. If you want to see an example of using polymorphism on device objects, take a look at my answer here. It demonstrates the idea of using the object itself to define the function you wish to perform on it. (Although, again, I don't think that is what you had in mind.)__device__
function in host code. This limitation can be worked around, after a fashion, by calling an "initialization kernel" which fills in a table of device function pointers for use in device code, but I think the net effect is no better than what I propose in 3 below.Here's an example which demonstrates this last idea: