When you put the __device__
decorator on your functor operator, you have now restricted what you can do in that operator body to things that are compatible with CUDA device code.
A thrust::device_vector
is a class definition that is designed to facilitate thrust's expression/computation model (roughly similar to STL containers/algorithms). As such it includes both host and device code in it. The host code in a thrust::device_vector
is not decorated for use on the device, and ordinary host code is not usable in CUDA device code.
thrust::device_vector
is not designed nor intended to be used directly in device code. It cannot be used as you have suggested. Contrary to what might be surmised, it is not designed to be an analog of std::vector
that is usable in CUDA device code. It is designed to be an analog of std::vector
that is usable in thrust algorithms (which, by design, are callable/usable from host code). This is why you are getting messages when compiling, and there is no trivial way(*) to fix that.
Presumably the primary purpose of the thrust::device_vector
is to act as a container to hold data that is usable/accessible on the device. The most direct equivalent in POD type data that is already supported in CUDA device code would be an array or a pointer to data.
Therefore I think its reasonable to answer your question with "yes" - that is the only way to achieve this.
- I am lumping in a variety of similar approaches, such as passing a thrust pointer instead of a bare pointer.
- (*)I am ignoring such ideas as writing your own container class that allows usage on the device, or making extensive modifications to thrust itself to somehow permit this behavior.
Here is a fully worked example, around what you have shown:
$ cat t1385.cu
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/transform.h>
#include <thrust/copy.h>
struct StructOperator : public thrust::unary_function<float, int> {
int num_;
int *v_test;
explicit StructOperator(int *input_v, int input_v_size) :
v_test(input_v), num_(input_v_size) {};
__host__ __device__
float operator()(int index) {
if (index < num_) return v_test[index] + 0.5;
return 0.0f;
}
};
const int ds = 3;
int main(){
thrust::device_vector<int> d(ds);
thrust::sequence(d.begin(), d.end());
thrust::device_vector<float> r(ds);
thrust::transform(d.begin(), d.end(), r.begin(), StructOperator(thrust::raw_pointer_cast(d.data()), d.size()));
thrust::copy(r.begin(), r.end(), std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl;
}
$ nvcc t1385.cu -o t1385
$ ./t1385
0.5,1.5,2.5,
$