使用推力在组中查找元素

时间:2015-12-24 13:10:32

标签: cuda thrust

我有两个用于键和值的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的方法非常好。

1 个答案:

答案 0 :(得分:4)

我会使用thrust::zip_iteratorzip 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,
$