Spaces:
Runtime error
Runtime error
| // 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<int> | |
| // or thrust::system::tbb::reference<float>, 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 <typename InputIterator, | |
| typename OutputIterator> | |
| 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<int> is not convertible to int& | |
| // assign_reference_to_reference(*in, *out); | |
| // valid - reference<int> explicitly converted to int& | |
| assign_reference_to_reference(thrust::raw_reference_cast(*in), thrust::raw_reference_cast(*out)); | |
| // valid - since reference<int> is convertible to int | |
| assign_value_to_reference(*in, thrust::raw_reference_cast(*out)); | |
| } | |
| }; | |
| template <typename Vector> | |
| 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<T>(std::cout, " ")); | |
| std::cout << "\n"; | |
| } | |
| int main(void) | |
| { | |
| typedef thrust::device_vector<int> 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<int,System>(0), | |
| thrust::counting_iterator<int,System>(N), | |
| copy_iterators<Iterator,Iterator>(A.begin(), B.begin())); | |
| std::cout << "After A->B Copy" << std::endl; | |
| print("A", A); | |
| print("B", B); | |
| return 0; | |
| } | |