Подсчитать количество уникальных элементов, используя thrust unique_by_key, когда набор значений является кортежем - PullRequest
0 голосов
/ 05 февраля 2019

Я пытаюсь использовать thrust :: unique по ключу, чтобы найти уникальный набор значений.Однако я использую кортеж для значений.Ключ имеет тип int, тип кортежа if (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

1 Ответ

0 голосов
/ 05 февраля 2019

Вот один из возможных подходов:

Как вы уже указали, thrust::unique_by_key возвращает пару итераторов.Пара в тяге является чем-то вроде кортежа, и мы можем использовать механизм доступа к элементу тяги кортежа (thrust::get<...>) для извлечения отдельных членов пары.

Поэтому, если мы получимпервый элемент пары, это соответствует конечному итератору результата для ключей , предоставленных алгоритму 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>


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
$
...