#include #include #include #include #include // This example illustrates how to use the raw_reference_cast to convert // system-specific reference wrappers into native references. // // Using iterators in the manner described here is generally discouraged. // Users should only resort to this technique if there is no viable // implemention of a given operation in terms of Thrust algorithms. // For example this particular example is better solved with thrust::copy, // which is safer and potentially faster. Only use this approach after all // safer alternatives have been exhausted. // // When a Thrust iterator is referenced (e.g. *iter) the result is not // a native or "raw" reference like int& or float&. Instead, // the result is a type such as thrust::system::cuda::reference // or thrust::system::tbb::reference, depending on the system // to which the data belongs. These reference wrappers are necessary // to make expressions like *iter1 = *iter2; work correctly when // iter1 and iter2 refer to data in different memory spaces on // heterogenous systems. // // The raw_reference_cast function essentially strips away the system-specific // meta-data so it should only be used when the code is guaranteed to be // executed within an appropriate context. __host__ __device__ void assign_reference_to_reference(int& x, int& y) { y = x; } __host__ __device__ void assign_value_to_reference(int x, int& y) { y = x; } template struct copy_iterators { InputIterator input; OutputIterator output; copy_iterators(InputIterator input, OutputIterator output) : input(input), output(output) {} __host__ __device__ void operator()(int i) { InputIterator in = input + i; OutputIterator out = output + i; // invalid - reference is not convertible to int& // assign_reference_to_reference(*in, *out); // valid - reference explicitly converted to int& assign_reference_to_reference(thrust::raw_reference_cast(*in), thrust::raw_reference_cast(*out)); // valid - since reference is convertible to int assign_value_to_reference(*in, thrust::raw_reference_cast(*out)); } }; template void print(const std::string& name, const Vector& v) { typedef typename Vector::value_type T; std::cout << name << ": "; thrust::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, " ")); std::cout << "\n"; } int main(void) { typedef thrust::device_vector Vector; typedef Vector::iterator Iterator; typedef thrust::device_system_tag System; size_t N = 5; // allocate device memory Vector A(N); Vector B(N); // initialize A and B thrust::sequence(A.begin(), A.end()); thrust::fill(B.begin(), B.end(), 0); std::cout << "Before A->B Copy" << std::endl; print("A", A); print("B", B); // note: we must specify the System to ensure correct execution thrust::for_each(thrust::counting_iterator(0), thrust::counting_iterator(N), copy_iterators(A.begin(), B.begin())); std::cout << "After A->B Copy" << std::endl; print("A", A); print("B", B); return 0; }