аргсорт в тяге - PullRequest
       26

аргсорт в тяге

4 голосов
/ 20 октября 2019

Допустимо ли использовать thrust::sort_by_key, как в следующем коде?

#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/sort.h>
#include <thrust/advance.h>
#include <thrust/copy.h>

#include <iterator>
#include <iostream>

int main()
{
    int init[] = {2, 1, 0, 3, 4};
    const thrust::device_vector< int > v{std::cbegin(init), std::cend(init)};

    thrust::device_vector< std::intptr_t > index{v.size()};
    thrust::sequence(index.begin(), index.end());

    auto key = thrust::make_permutation_iterator(thrust::make_transform_iterator(v.cbegin(), thrust::identity< thrust::tuple< int > >{}), index.cbegin());
    thrust::sort_by_key(key, thrust::next(key, index.size()), index.begin());

    thrust::copy(index.cbegin(), index.cend(), std::ostream_iterator< std::intptr_t >(std::cout, ", "));
    std::cout << std::endl;
}

Здесь index массив указывает на v массив значений. Я хочу иметь "отсортированный вид" ov v. index после сортировки выше - это представление, то есть сортируется [v[i] for i in index] (псевдокод питона).

Трюк с преобразованием identity имеет решающее значение: он преобразует значения, на которые указывает index в v в один элемент-кортеж. thrust::tuple является классом и имеет operator =, который не квалифицирован cv-ref только для lvalues ​​и, таким образом, может использоваться для значений r, только что возвращенных в результате разыменования transform_iterator. thrust::tuple< int >(1) = 2; является юридическим заявлением и фактически является запретом, потому что значение левой части упало сразу после назначения. В результате все перестановки ключей в sort_by_key являются бездействующими, а реальная сортировка происходит в части «значения» сортировки по ключу-значению.

Как я знаю, разработчики Thrust обычно предполагают, что все вызываемые объекты идемпотентная . Я полагаю, что предположение здесь не нарушается, потому что изменился только аргумент вызываемого (thrust::identity), а не состояние вызываемого. Но, с другой стороны, любая суперпозиция причудливых итераторов Thrust может рассматриваться как композиция функций (скажем, permutation_iterator - простое отображение).

...