I am trying to use sort_by_key() to sort key-value pairs, where the value is a zip_iterator
. But using this, only the keys are being sorted and not the value.
Here is my example code
#include <stdio.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>
#include <thrust/device_vector.h>
typedef thrust::device_vector<int>::iterator W_itr;
typedef thrust::tuple<W_itr, W_itr> W_itr_tuple;
typedef thrust::tuple<int, int> W_tuple;
struct Min_op
{
__host__ __device__
W_tuple operator()(const W_tuple& a, const W_tuple& b) const
{
int aw = thrust::get<0>(a), bw = thrust::get<0>(b);
return aw < bw ? a : b;
}
};
void printArray(int* a, int size)
{
printf("[ %d", a[0]);
for (int i = 1;i < size;i++)
{
printf(",\t%d", a[i]);
}
printf(" ]");
}
int main()
{
int a[5] = { 5, 4, 1, 4, 4 },
b[5] = { 1, 4, 2, 5, 6 },
c[5] = { 10, 11, 12,13,14 };
int* da, * db, * dc, * da_copy, * db_copy, * dc_copy;
int size = sizeof(int) * 5;
cudaMalloc(&da, size);
cudaMalloc(&db, size);
cudaMalloc(&dc, size);
cudaMalloc(&da_copy, size);
cudaMalloc(&db_copy, size);
cudaMalloc(&dc_copy, size);
cudaMemcpy(da, a, size, cudaMemcpyHostToDevice);
cudaMemcpy(db, b, size, cudaMemcpyHostToDevice);
cudaMemcpy(dc, c, size, cudaMemcpyHostToDevice);
thrust::device_ptr<int> da_ptr(da), db_ptr(db), dc_ptr(dc), db_copy_ptr(db_copy), dc_copy_ptr(dc_copy);
thrust::device_vector<int> b_vec(db, db + 5), c_vec(dc, dc + 5), b_vec_copy(db_copy_ptr, db_copy_ptr+5), c_vec_copy(dc_copy_ptr, dc_copy_ptr+5);
thrust::zip_iterator<W_itr_tuple> zip1(thrust::make_tuple(b_vec.begin(), c_vec.begin())),
zip2(thrust::make_tuple(b_vec_copy.begin(), c_vec_copy.begin())); // Question: Any easier way to make a zip_iterator with only raw pointers on device?
thrust::sort_by_key(da, da + 5, zip1);
cudaMemcpy(a, da, size, cudaMemcpyDeviceToHost);
cudaMemcpy(b, db, size, cudaMemcpyDeviceToHost);
cudaMemcpy(c, dc, size, cudaMemcpyDeviceToHost);
printf("After Sort\n a = ");
printArray(a, 5);
printf("\n b = ");
printArray(b, 5); // Question: Order has not changed at all. How to solve this?
printf("\n c = ");
printArray(c, 5); // Question: Order has not changed at all. How to solve this?
// auto result = thrust::reduce_by_key
// (
// da, da + 5,
// zip1,
// da_copy,
// zip2,
// thrust::equal_to<int>(),
// Min_op()
// );
// size = (result.first - da_copy) * sizeof(int); // Question: I am unable to get this compiled. Basically I want to use the zip_iterator to reduce using my custom operator. How to get this done?
cudaMemcpy(a, da_copy, size, cudaMemcpyDeviceToHost);
cudaMemcpy(b, db_copy, size, cudaMemcpyDeviceToHost);
cudaMemcpy(c, dc_copy, size, cudaMemcpyDeviceToHost);
printf("\n\nAfter Reduce\n a = ");
printArray(a, 5);
printf("\n b = ");
printArray(b, 5);
printf("\n c = ");
printArray(b, 5);
return 0;
}
And the output that I obtain here is
After Sort
a = [ 1, 4, 4, 4, 5 ]
b = [ 1, 4, 2, 5, 6 ]
c = [ 10, 11, 12, 13, 14 ]
...
As you can see, a is sorted correctly, but the b and c do not change as I expected them to.
I have put my queries in comments, which are the following:
- Assuming that my implementation is wrong, what is the correct/best way to declare a
zip_iterator
from raw device pointers? - How to get the zip_iteration sorted?
- How to use the
reduce_by_key()
function as I intend to? If I uncomment my code, it does not compile?