Question

I have been trying to use thrust function reduce_by_key on device vectors. In the documentation they have given example on host_vectors instead of any device vector. The main problem I am getting is in storing the return value of the function. To be more specific here is my code:

 thrust::device_vector<int> hashValueVector(10)
 thrust::device_vector<int> hashKeysVector(10)

 thrust::device_vector<int> d_pathId(10);
 thrust::device_vector<int> d_freqError(10); //EDITED 

 thrust::pair<thrust::detail::normal_iterator<thrust::device_ptr<int> >,thrust::detail::normal_iterator<thrust::device_ptr<int> > >  new_end; //THE PROBLEM
 new_end = thrust::reduce_by_key(hashKeysVector.begin(),hashKeysVector.end(),hashValueVector.begin(),d_pathId.begin(),d_freqError.begin());

I tried declaring them as device_ptr first in the definition since for host_vectors too they have used pointers in the definition in the documentation. But I am getting compilation error when I try that then I read the error statement and converted the declaration to the above, this is compiling fine but I am not sure whether this is the right way to define or not.

I there any other standard/clean way of declaring that (the "new_end" variable)? Please comment if my question is not clear somewhere.

EDIT: I have edited the declaration of d_freqError. It was supposed to be int I wrote it as hashElem by mistake, sorry for that.

Was it helpful?

Solution

There is a problem in the setup of your reduce_by_key operation:

new_end = thrust::reduce_by_key(hashKeysVector.begin(),hashKeysVector.end(),hashValueVector.begin(),d_pathId.begin(),d_freqError.begin());

Notice that in the documentation it states:

OutputIterator2 is a model of Output Iterator and and InputIterator2's value_type is convertible to OutputIterator2's value_type.

The value type of your InputIterator2 (i.e. hashValueVector.begin()) is int . The value type of your OutputIterator2 is struct hashElem. Thrust is not going to know how to convert an int to a struct hashElem.

Regarding your question, it should not be difficult to capture the return entity from reduce_by_key. According to the documentation it is a thrust pair of two iterators, and these iterators should be consistent with (i.e. of the same vector type and value type) as your keys iterator type and your values iterator type, respectively.

Here's an updated sample based on what you posted, which compiles cleanly:

$ cat t353.cu
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/pair.h>
#include <thrust/reduce.h>
#include <thrust/sequence.h>
#include <thrust/fill.h>
#include <thrust/copy.h>

typedef thrust::device_vector<int>::iterator  dIter;

int main(){

  thrust::device_vector<int> hashValueVector(10);
  thrust::device_vector<int> hashKeysVector(10);

  thrust::device_vector<int> d_pathId(10);
  thrust::device_vector<int> d_freqError(10);

  thrust::sequence(hashValueVector.begin(), hashValueVector.end());
  thrust::fill(hashKeysVector.begin(), hashKeysVector.begin()+5, 1);
  thrust::fill(hashKeysVector.begin()+6, hashKeysVector.begin()+10, 2);

  thrust::pair<dIter, dIter>  new_end;
  new_end = thrust::reduce_by_key(hashKeysVector.begin(),hashKeysVector.end(),hashValueVector.begin(),d_pathId.begin(),d_freqError.begin());
  std::cout << "Number of results are: " << new_end.first - d_pathId.begin() << std::endl;
  thrust::copy(d_pathId.begin(), new_end.first, std::ostream_iterator<int>(std::cout, "\n"));
  thrust::copy(d_freqError.begin(), new_end.second, std::ostream_iterator<int>(std::cout, "\n"));
}

$ nvcc -arch=sm_20 -o t353 t353.cu
$ ./t353
Number of results are: 3
1
0
2
10
5
30
$
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top