我有两个用于键和值的int向量,它们的大小约为500K。
键向量已经排序。并且大约有10K组。
该值为非负(代表有用)或-2(代表无用),每组中应有一个或零个非负值,其余为-2。
key: 0 0 0 0 1 2 2 3 3 3 3
value:-2 -2 1 -2 3 -2 -2 -2 -2 -2 0
第三组0 [0 1]
非常有用。对于第1组,我们得到了[1 3]
对。第2组的值都是-2,所以我们什么也得不到。对于第3组,结果为[3 0]
。
所以,问题是如何通过推力或者cuda来做到这一点?
这是两个想法。
第一个:
通过直方图算法获取每个组的编号。因此可以计算每组的障碍。
在每个组上操作thrust::find_if
以获得有用的元素。
第二个:
使用thrust::transform
为每个值添加2,现在所有值都是非负值,零代表无用。
使用thrust::reduce_by_key
获取每个组的缩减,然后为每个输出值减去2。
我认为必须有一些其他方法可以获得比上述两种方法更多的性能。
方法的表现:
我测试了上面的第二方法和 @Robert Crovella 给出的方法,即。 reduce_by_key 和 remove_if 方法。 载体的大小为2691028,载体由100001组组成。这是他们的平均时间:
reduce_by_key: 1204ms
remove_if: 192ms
从上面的结果中,我们可以看到remove_if方法要快得多。还有" remove_if"方法易于实现,消耗的GPU内存更少。
简单地说,@ Rortrt Crovella的方法非常好。
答案 0 :(得分:4)
我会使用thrust::zip_iterator
到zip the key and values pairs together,然后我会对压缩值执行thrust::remove_if
操作,这需要一个函子定义,表明要删除每对价值是负的(或任何你想要的测试。)
这是一个有效的例子:
$ cat t1009.cu
#include <thrust/remove.h>
#include <thrust/device_vector.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/copy.h>
struct remove_func
{
template <typename T>
__host__ __device__
bool operator()(T &t){
return (thrust::get<1>(t) < 0); // could change to other kinds of tests
}
};
int main(){
int keys[] = {0,0,0,0,1,2,2,3,3,3,3};
int vals[] = {-2,-2,1,-2,3,-2,-2,-2,-2,-2,0};
size_t dsize = sizeof(keys)/sizeof(int);
thrust::device_vector<int>dkeys(keys, keys+dsize);
thrust::device_vector<int>dvals(vals, vals+dsize);
auto zr = thrust::make_zip_iterator(thrust::make_tuple(dkeys.begin(), dvals.begin()));
size_t rsize = thrust::remove_if(zr, zr+dsize, remove_func()) - zr;
thrust::copy_n(dkeys.begin(), rsize, std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
thrust::copy_n(dvals.begin(), rsize, std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
return 0;
}
$ nvcc -std=c++11 -o t1009 t1009.cu
$ ./t1009
0,1,3,
1,3,0,
$