Question

What is the canonical way to derive from one of the fancy iterators of the thrust framework?

I'm storing 3D points in a structure of arrays. Now I was thinking about a convenient way to get a blas vector type from that. What I came up with was something like this:

namespace abc {
  typedef VERY_BASIC_LINEAR_ALGEBRA_VECTOR_CLASS_FOR_TESTING t_vector;
  typedef typename thrust::device_vector::iterator t_baseIterator;
  typedef typename thrust::tuple<t_baseIterator,t_baseIterator,t_baseIterator> t_iteratorTuple;
  typedef typename thrust::zip_iterator<t_iteratorTuple> t_zipIterator;

  struct custom_iterator: public t_zipIterator {
    custom_iterator(t_zipIterator zi): t_zipIterator(zi) {}
    t_vector getVector() {
      return t_vector(**this);
    }
    void setVector(const t_vector& v) {
      **this = (t_tuple)v;
    }
  };
}

This works. Which means I can do something like it.getVector() (where it is a valid custom_iterator), and pass this custom_iterators to thrusts compute primitives, like transform_reduce. I've searched a little bit more about the documentation of thrust and found thrust::iterator_adaptor. Now the question: should one rather use iterator_adaptor? If so, why? What are the pros and cons of above piece of code. It seems rather exaggerated using iterator_adaptor:

#include <thrust/iterator/iterator_adaptor.h>
class custom_iterator: public thrust::iterator_adaptor<custom_iterator, t_zipIterator> {
    public:
    typedef thrust::iterator_adaptor<custom_iterator, t_zipIterator> super_t;

    custom_iterator(const t_zipIterator &zi) : super_t(zi) {}

    t_vector getVector() {
        return t_vector(**this);
    }
    void setVector(const t_vector& v) {
        **this = (t_tuple)v;
    }

    friend class thrust::iterator_core_access;
};

I don't know if this works, as I didn't try.

So the question is: What is the canonical way doing this?

Related to this is another question: A functor used by thrust::transform_reduce or thrust::transform_iterator must accept the underlying type of a given iterator, not the iterator itself. So above custom_iterator is pretty much useless. Is there a way to accept an iterator instead of an dereferenced iterator in the operator() member function of the used functor?

You may ask yourself why I want a derived iterator with this additonal getters and setters, as above examples suggest that t_vector is initialised with the underling tuple of the zip_iterator anyway. But this is only an example, and there is a more complex case, where above concept would be a very convenient way to go.

Was it helpful?

Solution

As I couldn't find a virtual destructor neither in thrust::zip_iterator nor in thrust::iterator_adaptor, I guess it's a bad idea to derive from either one.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top