Spaces:
Runtime error
Runtime error
// 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 Iterator> | |
class range_view | |
{ | |
public: | |
typedef Iterator iterator; | |
typedef typename thrust::iterator_traits<iterator>::value_type value_type; | |
typedef typename thrust::iterator_traits<iterator>::pointer pointer; | |
typedef typename thrust::iterator_traits<iterator>::difference_type difference_type; | |
typedef typename thrust::iterator_traits<iterator>::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<iterator> rbegin() | |
{ | |
return thrust::reverse_iterator<iterator>(end()); | |
} | |
__host__ __device__ | |
const thrust::reverse_iterator<const iterator> crbegin() const | |
{ | |
return thrust::reverse_iterator<const iterator>(cend()); | |
} | |
__host__ __device__ | |
thrust::reverse_iterator<iterator> rend() | |
{ | |
return thrust::reverse_iterator<iterator>(begin()); | |
} | |
__host__ __device__ | |
const thrust::reverse_iterator<const iterator> crend() const | |
{ | |
return thrust::reverse_iterator<const 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 <class Iterator, class Size> | |
range_view<Iterator> | |
__host__ __device__ | |
make_range_view(Iterator first, Size n) | |
{ | |
return range_view<Iterator>(first, first+n); | |
} | |
// This helper function creates a range_view from a pair of iterators | |
template <class Iterator> | |
range_view<Iterator> | |
__host__ __device__ | |
make_range_view(Iterator first, Iterator last) | |
{ | |
return range_view<Iterator>(first, last); | |
} | |
// This helper function creates a range_view from a Vector | |
template <class Vector> | |
range_view<typename Vector::iterator> | |
__host__ | |
make_range_view(Vector& v) | |
{ | |
return range_view<typename Vector::iterator>(v.begin(), v.end()); | |
} | |
// This saxpy functor stores view of X, Y, Z array, and accesses them in | |
// vector-like way | |
template<class View1, class View2, class View3> | |
struct saxpy_functor : public thrust::unary_function<int,void> | |
{ | |
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<class View1, class View2, class View3> | |
__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<View1,View2,View3>(A,X,Y,Z)); | |
} | |
struct f1 : public thrust::unary_function<float,float> | |
{ | |
__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<float> X(x, x + 4); | |
thrust::device_vector<float> Y(y, y + 4); | |
thrust::device_vector<float> 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<float> 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; | |
} | |