#include #include #include #include #include // This example demonstrates the use of a view: a non-owning wrapper for an // iterator range which presents a container-like interface to the user. // // For example, a view of a device_vector's data can be helpful when we wish to // access that data from a device function. Even though device_vectors are not // accessible from device functions, the range_view class allows us to access // and manipulate its data as if we were manipulating a real container. template class range_view { public: typedef Iterator iterator; typedef typename thrust::iterator_traits::value_type value_type; typedef typename thrust::iterator_traits::pointer pointer; typedef typename thrust::iterator_traits::difference_type difference_type; typedef typename thrust::iterator_traits::reference reference; private: const iterator first; const iterator last; public: __host__ __device__ range_view(Iterator first, Iterator last) : first(first), last(last) {} __host__ __device__ ~range_view() {} __host__ __device__ difference_type size() const { return thrust::distance(first, last); } __host__ __device__ reference operator[](difference_type n) { return *(first + n); } __host__ __device__ const reference operator[](difference_type n) const { return *(first + n); } __host__ __device__ iterator begin() { return first; } __host__ __device__ const iterator cbegin() const { return first; } __host__ __device__ iterator end() { return last; } __host__ __device__ const iterator cend() const { return last; } __host__ __device__ thrust::reverse_iterator rbegin() { return thrust::reverse_iterator(end()); } __host__ __device__ const thrust::reverse_iterator crbegin() const { return thrust::reverse_iterator(cend()); } __host__ __device__ thrust::reverse_iterator rend() { return thrust::reverse_iterator(begin()); } __host__ __device__ const thrust::reverse_iterator crend() const { return thrust::reverse_iterator(cbegin()); } __host__ __device__ reference front() { return *begin(); } __host__ __device__ const reference front() const { return *cbegin(); } __host__ __device__ reference back() { return *end(); } __host__ __device__ const reference back() const { return *cend(); } __host__ __device__ bool empty() const { return size() == 0; } }; // This helper function creates a range_view from iterator and the number of // elements template range_view __host__ __device__ make_range_view(Iterator first, Size n) { return range_view(first, first+n); } // This helper function creates a range_view from a pair of iterators template range_view __host__ __device__ make_range_view(Iterator first, Iterator last) { return range_view(first, last); } // This helper function creates a range_view from a Vector template range_view __host__ make_range_view(Vector& v) { return range_view(v.begin(), v.end()); } // This saxpy functor stores view of X, Y, Z array, and accesses them in // vector-like way template struct saxpy_functor : public thrust::unary_function { const float a; View1 x; View2 y; View3 z; __host__ __device__ saxpy_functor(float _a, View1 _x, View2 _y, View3 _z) : a(_a), x(_x), y(_y), z(_z) { } __host__ __device__ void operator()(int i) { z[i] = a * x[i] + y[i]; } }; // saxpy function, which can either be called form host or device // The views are passed by value template __host__ __device__ void saxpy(float A, View1 X, View2 Y, View3 Z) { // Z = A * X + Y const int size = X.size(); thrust::for_each(thrust::device, thrust::make_counting_iterator(0), thrust::make_counting_iterator(size), saxpy_functor(A,X,Y,Z)); } struct f1 : public thrust::unary_function { __host__ __device__ float operator()(float x) const { return x*3; } }; int main() { using std::cout; using std::endl; // initialize host arrays float x[4] = {1.0, 1.0, 1.0, 1.0}; float y[4] = {1.0, 2.0, 3.0, 4.0}; float z[4] = {0.0}; thrust::device_vector X(x, x + 4); thrust::device_vector Y(y, y + 4); thrust::device_vector Z(z, z + 4); saxpy( 2.0, // make a range view of a pair of transform_iterators make_range_view(thrust::make_transform_iterator(X.cbegin(), f1()), thrust::make_transform_iterator(X.cend(), f1())), // range view of normal_iterators make_range_view(Y.begin(), thrust::distance(Y.begin(), Y.end())), // range view of naked pointers make_range_view(Z.data().get(), 4)); // print values from original device_vector Z // to ensure that range view was mapped to this vector for (int i = 0, n = Z.size(); i < n; ++i) { cout << "z[" << i << "]= " << Z[i] << endl; } return 0; }