Как динамически установить размер device_vectors в операциях установки тяги? - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть два набора A и B. В результате (C) моей операции должны быть элементы в A, которых нет в B. Я использую set_difference, чтобы сделать это.Однако размер результата (C) должен быть установлен перед операцией.В противном случае он имеет дополнительные нули в конце, как показано ниже:

A=
1 2 3 4 5 6 7 8 9 10 
B=
1 2 8 11 7 4 
C=
3 5 6 9 10 0 0 0 0 0 

Как динамически установить размер результата (C) так, чтобы на выходе было C= 3 5 6 9.В реальной проблеме я бы не знал требуемый размер результата device_vector apriori.

Мой код:

#include <thrust/execution_policy.h>
#include <thrust/set_operations.h>
#include <thrust/sequence.h>
#include <thrust/execution_policy.h>
#include <thrust/device_vector.h>


void remove_common_elements(thrust::device_vector<int> A, thrust::device_vector<int> B, thrust::device_vector<int>& C)
{

thrust::sort(thrust::device, A.begin(), A.end());
thrust::sort(thrust::device, B.begin(), B.end());

thrust::set_difference(thrust::device, A.begin(), A.end(), B.begin(), B.end(), C.begin());
}

int main(int argc, char * argv[])
{

thrust::device_vector<int> A(10);
thrust::sequence(thrust::device, A.begin(), A.end(),1);  // x components of the 'A' vectors

thrust::device_vector<int> B(6);
B[0]=1;B[1]=2;B[2]=8;B[3]=11;B[4]=7;B[5]=4;

thrust::device_vector<int> C(A.size());

std::cout << "A="<< std::endl;
thrust::copy(A.begin(), A.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;

std::cout << "B="<< std::endl;
thrust::copy(B.begin(), B.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;

remove_common_elements(A, B, C);

std::cout << "C="<< std::endl;
thrust::copy(C.begin(), C.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;

return 0;
}

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

thrust::set_difference возвращает итератор в конец результирующего диапазона.

Если вы просто хотите изменить логический размер C на количество результирующих элементов, вы можете просто стереть диапазон «позади»диапазон результатов.

void remove_common_elements(thrust::device_vector<int> A, 
thrust::device_vector<int> B, thrust::device_vector<int>& C)
{

    thrust::sort(thrust::device, A.begin(), A.end());
    thrust::sort(thrust::device, B.begin(), B.end());

    auto C_end = thrust::set_difference(thrust::device, A.begin(), A.end(), B.begin(), B.end(), C.begin());
    C.erase(C_end, C.end());
}
0 голосов
/ 11 декабря 2018

В общем случае (т. Е. Для различных алгоритмов тяги) часто нет способа узнать размер выходного документа, кроме как быть верхней границей.Обычный подход здесь состоит в том, чтобы передать вектор результата, размер которого является верхней границей возможного выходного размера.Как вы уже заявили, во многих случаях фактический размер выходных данных не может быть известен априори.У тяги нет особой магии, чтобы решить это.После операции вы узнаете размер результата, и он может быть скопирован в новый вектор, если «дополнительные нули» были проблемой по какой-то причине (я не могу придумать причину, по которой они будут проблемой вообще, за исключением того, что они занимают выделенное пространство).

Если это крайне нежелательно, одна из возможностей (копирование этой информации из ответа Джареда Хоберока в на другом форуме ) - запустить алгоритм дважды , первый раз с использованием discard_iterator (для выходных данных) и второй раз с реальным итератором, указывающим на фактическое распределение векторов, требуемого размера.Во время первого прохода discard_iterator используется для подсчета размера фактических данных результата, даже если они нигде не хранятся.Цитируя непосредственно от Джареда:

На первом этапе передайте discard_iterator в качестве выходного итератора.Вы можете сравнить discard_iterator, возвращенный как результат, чтобы вычислить размер вывода.На втором этапе вызовите алгоритм «по-настоящему» и выведите его в массив, размер которого зависит от результата первого этапа.

Техника продемонстрирована в примере set_operations.cu [0,1]:

[0] https://github.com/thrust/thrust/blob/master/examples/set_operations.cu#L25

[1] https://github.com/thrust/thrust/blob/master/examples/set_operations.cu#L127

...