当值集是元组时,使用 thrust unique_by_key 计算唯一元素的数量
Count number of unique elements using thrust unique_by_key when the set of values is a tuple
我正在尝试使用 thrust::unique 键来查找一组唯一的值。但是我使用元组作为值。键是int类型,元组是类型(float, int)。
我的以下代码可以很好地找到一组唯一值。 但是我还需要计算唯一值的数量。
我看过推力示例,但是当值为元组时我无法声明输出迭代器类型
thrust::pair<int*,int*> new_end;
new_end = thrust::unique_by_key(thrust::host, A, A + N, B);
检测到唯一性后我的代码和输出如下。 请告诉我如何计算唯一元素的数量。
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/unique.h>
int main()
{
const int N = 8;
thrust::device_vector<int> keys1(N);
thrust::device_vector<int> keys2(N);
thrust::device_vector<float> value_keys(N);
keys1[0] = 1; keys1[1] = 1; keys1[2] = 2; keys1[3] = 2;
keys1[4] = 2; keys1[5] = 3; keys1[6] = 3; keys1[7] = 3;
keys2[0] = 4; keys2[1] = 1; keys2[2] = 7; keys2[3] = 2;
keys2[4] = 6; keys2[5] = 8; keys2[6] = 3; keys2[7] = 5;
value_keys[0] = -0.01; value_keys[1] = 1.1; value_keys[2] = -0.07; value_keys[3] = 2.1;
value_keys[4] = 5.2; value_keys[5] = -0.08; value_keys[6] = 3.2; value_keys[7] = 5.1;
thrust::unique_by_key(thrust::device, keys1.begin(), keys1.end(),
thrust::make_zip_iterator(thrust::make_tuple(value_keys.begin(), keys2.begin())));
std::cout << "Unique PAIRS:"<< std::endl;
std::cout << "keys1, value_keys, keys2:" << std::endl;
for (int i = 0; i < N; i++) {
std::cout << keys1[i] <<'\t' << value_keys[i] <<'\t' << keys2[i] << std::endl;
}
}
输出:
Unique PAIRS:
keys1, value_keys, keys2:
1 -0.01 4
2 -0.07 7
3 -0.08 8
2 2.1 2
2 5.2 6
3 -0.08 8
3 3.2 3
3 5.1 5
这是一种可能的方法:
正如您已经指出的那样,thrust::unique_by_key
returns a pair of iterators. A pair in thrust is something like a tuple, and we can use the thrust tuple element access mechanism (thrust::get<...>
) 检索对中的单个成员。
因此,如果我们检索该对的第一个元素,这对应于提供给 thrust::unique_by_key
算法的 keys 的结果结束迭代器。我们可以从中减去键的开始迭代器,以检索结果中键的长度(与结果中值的长度相同)。
这是一个有效的例子:
$ cat t390.cu
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/unique.h>
int main()
{
const int N = 8;
thrust::device_vector<int> keys1(N);
thrust::device_vector<int> keys2(N);
thrust::device_vector<float> value_keys(N);
keys1[0] = 1; keys1[1] = 1; keys1[2] = 2; keys1[3] = 2;
keys1[4] = 2; keys1[5] = 3; keys1[6] = 3; keys1[7] = 3;
keys2[0] = 4; keys2[1] = 1; keys2[2] = 7; keys2[3] = 2;
keys2[4] = 6; keys2[5] = 8; keys2[6] = 3; keys2[7] = 5;
value_keys[0] = -0.01; value_keys[1] = 1.1; value_keys[2] = -0.07; value_keys[3] = 2.1;
value_keys[4] = 5.2; value_keys[5] = -0.08; value_keys[6] = 3.2; value_keys[7] = 5.1;
auto end = thrust::unique_by_key(thrust::device, keys1.begin(), keys1.end(),
thrust::make_zip_iterator(thrust::make_tuple(value_keys.begin(), keys2.begin())));
int result_size = thrust::get<0>(end) - keys1.begin();
std::cout << "Unique PAIRS:"<< std::endl;
std::cout << "keys1, value_keys, keys2:" << std::endl;
for (int i = 0; i < result_size; i++) {
std::cout << keys1[i] <<'\t' << value_keys[i] <<'\t' << keys2[i] << std::endl;
}
}
$ nvcc -o t390 t390.cu -std=c++11
$ ./t390
Unique PAIRS:
keys1, value_keys, keys2:
1 -0.01 4
2 -0.07 7
3 -0.08 8
$
如果您不想使用 c++11 auto
,那么您可以通过自己明确定义返回的对来修改上面的示例。这是通过查看 thrust::unique_by_key
算法使用的两个输入迭代器类型并从中创建一对来确定的。这是一个例子:
$ cat t390.cu
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/unique.h>
typedef thrust::zip_iterator<thrust::tuple<thrust::device_vector<float>::iterator, thrust::device_vector<int>::iterator> > my_iter;
typedef thrust::pair<thrust::device_vector<int>::iterator, my_iter> my_pair;
int main()
{
const int N = 8;
thrust::device_vector<int> keys1(N);
thrust::device_vector<int> keys2(N);
thrust::device_vector<float> value_keys(N);
keys1[0] = 1; keys1[1] = 1; keys1[2] = 2; keys1[3] = 2;
keys1[4] = 2; keys1[5] = 3; keys1[6] = 3; keys1[7] = 3;
keys2[0] = 4; keys2[1] = 1; keys2[2] = 7; keys2[3] = 2;
keys2[4] = 6; keys2[5] = 8; keys2[6] = 3; keys2[7] = 5;
value_keys[0] = -0.01; value_keys[1] = 1.1; value_keys[2] = -0.07; value_keys[3] = 2.1;
value_keys[4] = 5.2; value_keys[5] = -0.08; value_keys[6] = 3.2; value_keys[7] = 5.1;
my_pair end = thrust::unique_by_key(thrust::device, keys1.begin(), keys1.end(),
thrust::make_zip_iterator(thrust::make_tuple(value_keys.begin(), keys2.begin())));
int result_size = thrust::get<0>(end) - keys1.begin();
std::cout << "Unique PAIRS:"<< std::endl;
std::cout << "keys1, value_keys, keys2:" << std::endl;
for (int i = 0; i < result_size; i++) {
std::cout << keys1[i] <<'\t' << value_keys[i] <<'\t' << keys2[i] << std::endl;
}
}
$ nvcc -o t390 t390.cu
$ ./t390
Unique PAIRS:
keys1, value_keys, keys2:
1 -0.01 4
2 -0.07 7
3 -0.08 8
$
我正在尝试使用 thrust::unique 键来查找一组唯一的值。但是我使用元组作为值。键是int类型,元组是类型(float, int)。
我的以下代码可以很好地找到一组唯一值。 但是我还需要计算唯一值的数量。
我看过推力示例,但是当值为元组时我无法声明输出迭代器类型
thrust::pair<int*,int*> new_end;
new_end = thrust::unique_by_key(thrust::host, A, A + N, B);
检测到唯一性后我的代码和输出如下。 请告诉我如何计算唯一元素的数量。
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/unique.h>
int main()
{
const int N = 8;
thrust::device_vector<int> keys1(N);
thrust::device_vector<int> keys2(N);
thrust::device_vector<float> value_keys(N);
keys1[0] = 1; keys1[1] = 1; keys1[2] = 2; keys1[3] = 2;
keys1[4] = 2; keys1[5] = 3; keys1[6] = 3; keys1[7] = 3;
keys2[0] = 4; keys2[1] = 1; keys2[2] = 7; keys2[3] = 2;
keys2[4] = 6; keys2[5] = 8; keys2[6] = 3; keys2[7] = 5;
value_keys[0] = -0.01; value_keys[1] = 1.1; value_keys[2] = -0.07; value_keys[3] = 2.1;
value_keys[4] = 5.2; value_keys[5] = -0.08; value_keys[6] = 3.2; value_keys[7] = 5.1;
thrust::unique_by_key(thrust::device, keys1.begin(), keys1.end(),
thrust::make_zip_iterator(thrust::make_tuple(value_keys.begin(), keys2.begin())));
std::cout << "Unique PAIRS:"<< std::endl;
std::cout << "keys1, value_keys, keys2:" << std::endl;
for (int i = 0; i < N; i++) {
std::cout << keys1[i] <<'\t' << value_keys[i] <<'\t' << keys2[i] << std::endl;
}
}
输出:
Unique PAIRS:
keys1, value_keys, keys2:
1 -0.01 4
2 -0.07 7
3 -0.08 8
2 2.1 2
2 5.2 6
3 -0.08 8
3 3.2 3
3 5.1 5
这是一种可能的方法:
正如您已经指出的那样,thrust::unique_by_key
returns a pair of iterators. A pair in thrust is something like a tuple, and we can use the thrust tuple element access mechanism (thrust::get<...>
) 检索对中的单个成员。
因此,如果我们检索该对的第一个元素,这对应于提供给 thrust::unique_by_key
算法的 keys 的结果结束迭代器。我们可以从中减去键的开始迭代器,以检索结果中键的长度(与结果中值的长度相同)。
这是一个有效的例子:
$ cat t390.cu
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/unique.h>
int main()
{
const int N = 8;
thrust::device_vector<int> keys1(N);
thrust::device_vector<int> keys2(N);
thrust::device_vector<float> value_keys(N);
keys1[0] = 1; keys1[1] = 1; keys1[2] = 2; keys1[3] = 2;
keys1[4] = 2; keys1[5] = 3; keys1[6] = 3; keys1[7] = 3;
keys2[0] = 4; keys2[1] = 1; keys2[2] = 7; keys2[3] = 2;
keys2[4] = 6; keys2[5] = 8; keys2[6] = 3; keys2[7] = 5;
value_keys[0] = -0.01; value_keys[1] = 1.1; value_keys[2] = -0.07; value_keys[3] = 2.1;
value_keys[4] = 5.2; value_keys[5] = -0.08; value_keys[6] = 3.2; value_keys[7] = 5.1;
auto end = thrust::unique_by_key(thrust::device, keys1.begin(), keys1.end(),
thrust::make_zip_iterator(thrust::make_tuple(value_keys.begin(), keys2.begin())));
int result_size = thrust::get<0>(end) - keys1.begin();
std::cout << "Unique PAIRS:"<< std::endl;
std::cout << "keys1, value_keys, keys2:" << std::endl;
for (int i = 0; i < result_size; i++) {
std::cout << keys1[i] <<'\t' << value_keys[i] <<'\t' << keys2[i] << std::endl;
}
}
$ nvcc -o t390 t390.cu -std=c++11
$ ./t390
Unique PAIRS:
keys1, value_keys, keys2:
1 -0.01 4
2 -0.07 7
3 -0.08 8
$
如果您不想使用 c++11 auto
,那么您可以通过自己明确定义返回的对来修改上面的示例。这是通过查看 thrust::unique_by_key
算法使用的两个输入迭代器类型并从中创建一对来确定的。这是一个例子:
$ cat t390.cu
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/unique.h>
typedef thrust::zip_iterator<thrust::tuple<thrust::device_vector<float>::iterator, thrust::device_vector<int>::iterator> > my_iter;
typedef thrust::pair<thrust::device_vector<int>::iterator, my_iter> my_pair;
int main()
{
const int N = 8;
thrust::device_vector<int> keys1(N);
thrust::device_vector<int> keys2(N);
thrust::device_vector<float> value_keys(N);
keys1[0] = 1; keys1[1] = 1; keys1[2] = 2; keys1[3] = 2;
keys1[4] = 2; keys1[5] = 3; keys1[6] = 3; keys1[7] = 3;
keys2[0] = 4; keys2[1] = 1; keys2[2] = 7; keys2[3] = 2;
keys2[4] = 6; keys2[5] = 8; keys2[6] = 3; keys2[7] = 5;
value_keys[0] = -0.01; value_keys[1] = 1.1; value_keys[2] = -0.07; value_keys[3] = 2.1;
value_keys[4] = 5.2; value_keys[5] = -0.08; value_keys[6] = 3.2; value_keys[7] = 5.1;
my_pair end = thrust::unique_by_key(thrust::device, keys1.begin(), keys1.end(),
thrust::make_zip_iterator(thrust::make_tuple(value_keys.begin(), keys2.begin())));
int result_size = thrust::get<0>(end) - keys1.begin();
std::cout << "Unique PAIRS:"<< std::endl;
std::cout << "keys1, value_keys, keys2:" << std::endl;
for (int i = 0; i < result_size; i++) {
std::cout << keys1[i] <<'\t' << value_keys[i] <<'\t' << keys2[i] << std::endl;
}
}
$ nvcc -o t390 t390.cu
$ ./t390
Unique PAIRS:
keys1, value_keys, keys2:
1 -0.01 4
2 -0.07 7
3 -0.08 8
$