Search code examples
c++cudagpgputhrust

What is the point of the make_transform_iterator as the second parameter in thrust::reduce algorithm?


The code is as follows:

thrust::reduce(thrust::make_transform_iterator(v.begin(), square()),
                  thrust::make_transform_iterator(v.end(),   square()));

Taken from transform_iterator example here. Specifically, isn't it redundant to use the following as the second iterator?

thrust::make_transform_iterator(v.end(), square())

Why not just use the following in its place?

 thrust::reduce(thrust::make_transform_iterator(v.begin(), square()),
                  v.end());

I suppose in this particular example, since thrust::make_transform_iterator(v.begin(), square()) does not produce an iterator that is of different size than v, my updated code would do the same thing as the original, is that correct?

EDIT
My only guess is that it's to make sure both iterators are of the same type? All I found to confirm my suspicion on this was the following text in that documentation "the transform functor (namely square_root and square) inherits from thrust::unary_function. Inheriting from thrust::unary_function ensures that a functor is a valid AdaptableUnaryFunction and provides all the necessary typedef declarations." Although, I think this specifically is referring to the functor itself.

UPDATE
See Robert Crovella's comment for answer.


Solution

  • The iterators here are used to mark the beginning and ending of a specific sequence. v.end() does not mark the end of the sequence that the transform iterator here:

    thrust::reduce(thrust::make_transform_iterator(v.begin(), square()),
                  v.end());
    

    marks the start of.

    Some other constructs here might have a better appearance (beauty is in the eye of the beholder), such as:

    auto my_iter = thrust::make_transform_iterator(v.begin(), square());
    thrust::reduce(my_iter, my_iter+v.size());