'How to get thrust::unique() to work with a vector of thrust::pair
I'm trying to make a unique thrust device vector of thrust::pair<int, int> using thrust::unique(), but the resulting output doesn't seem to be sorted like it should be. Here's the code in question:
struct make_pair : public thrust::binary_function<int, int, thrust::pair<int, int>> {
__host__ __device__
thrust::pair<int, int> operator()(int x, int y) { return thrust::make_pair(x, y); }
};
std::vector<thrust::pair<int, int>> find_borders_launch(int src_width, int src_height, cv::cuda::GpuMat& d_src) {
thrust::device_vector<int> d_focus_result(src_width * src_height * 9);
thrust::device_vector<int> d_target_result(src_width * src_height * 9);
int* d_focus = thrust::raw_pointer_cast(d_focus_result.data());
int* d_target = thrust::raw_pointer_cast(d_target_result.data());
dim3 num_blocks = {uint(src_width + 1), uint(src_height + 1)};
dim3 threads_per_block = {9, 1, 1};
int substep_size = sizeof(int);
find_borders_kernel <<<num_blocks, threads_per_block>>> (src_width, src_height, d_src.data, d_src.step, d_focus, d_target, substep_size);
thrust::device_vector<thrust::pair<int, int>> d_unique(d_focus_result.size());
thrust::transform(d_focus_result.begin(), d_focus_result.end(), d_target_result.begin(), d_unique.begin(), make_pair() ); //seems to do its job just fine
thrust::unique(thrust::device, d_unique.begin(), d_unique.end());
std::vector<thrust::pair<int, int>> output(d_unique.size());
thrust::copy(d_unique.begin(), d_unique.end(), output.begin() );
return output;
}
and the output looks something like:
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 76
-1, -1
0, 76
0, 0
76, 0
-1, -1
76, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
76, 142
-1, -1
76, 142
0, 0
142, 76
-1, -1
142, 76
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
-1, -1
0, 0
...
...
...
and so on for eight million more entries. The documentation says that the first N = num_unique_elements of the array should be all the unique values, but they're clearly not. My second issue- I want to do something like this to cut off the garbage values at the end of the unique vector:
T* new_end = thrust::unique(thrust::device, d_unique.begin(), d_unique.end());
std::vector<thrust::pair<int, int>> output(int(new_end));
thrust::copy(d_unique.begin(), d_unique.begin() + new_end, output.begin() );
but that code throws an error ('T' is not actually part of the code but stands for many different types I have tried so far). I have a feeling I'm going about both parts of this question in the complete wrong way, and based on the fact that I can't find any questions about it on google, I assume the answer is obvious for reasons I am ignorant of.
Solution 1:[1]
solved, thanks to paleonix's comments. I had to sort the array before running unique on it, and the return value of unique wanted to go into thrust::device_vector<thrust::pair<int, int>>::iterator. here's the changed code if anyone in the future comes across the same problem. I'm sure it's super janky, but it works.
thrust::device_vector<thrust::pair<int, int>> d_unique(d_focus_result.size());
thrust::transform(d_focus_result.begin(), d_focus_result.end(), d_target_result.begin(), d_unique.begin(), make_pair() ); //seems to do its job just fine
thrust::sort(thrust::device, d_unique.begin(), d_unique.end());
thrust::device_vector<thrust::pair<int, int>>::iterator new_end = thrust::unique(thrust::device, d_unique.begin(), d_unique.end());
int new_length = thrust::distance(d_unique.begin(), new_end);
std::vector<thrust::pair<int, int>> output(new_length);
thrust::copy(d_unique.begin(), d_unique.begin() + new_length, output.begin() );
return output;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | classic_sasquatch_behavior |
