如何在推力集操作中动态设置device_vectors的大小?

How to dynamically set the size of device_vectors in thrust set operations?

我有两组 A 和 B。我的操作结果 (C) 应该包含 A 中的元素,而 B 中没有。我使用 set_difference 来完成它。但是必须在操作之前设置 result(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 

如何动态设置 result(C) 的大小以使输出为 C= 3 5 6 9。在实际问题中,我不知道 result 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;
}

在一般情况下(即跨各种推力算法)通常没有办法知道输出大小,除了上限是多少。这里通常的方法是传递一个结果向量,其大小是可能输出大小的上限。正如您已经说过的,在许多情况下,无法先验地知道输出的实际大小。 Thrust 没有特别的魔法来解决这个问题。操作后,您将知道结果的大小,如果 "extra zeroes" 由于某种原因出现问题(我想不出它们会成为问题的原因),则可以将其复制到新向量一般来说,除了他们用完分配的 space).

如果这是非常令人反感的,一种可能性(从 Jared Hoberock 在 another forum) is to run the algorithm twice, the first time using a discard_iterator 的响应中复制此信息(对于输出数据),第二次使用真正的迭代器,指向实际的向量分配, 必要的大小。在第一遍中,discard_iterator 用于计算实际结果数据的大小,即使它没有存储在任何地方。直接引用 Jared 的话:

在第一阶段,传递一个discard_iterator作为输出迭代器。您可以比较作为结果返回的 discard_iterator 来计算输出的大小。在第二阶段,调用算法 "for real" 并输出到使用第一阶段结果确定大小的数组中。

该技术在 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

thrust::set_difference returns 指向结果范围末尾的迭代器。

如果您只想将 C 的逻辑大小更改为结果元素的数量,您可以简单地擦除范围 "behind" 结果范围。

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());
}