我有兴趣移植一些现有的代码以使用推力,以查看是否可以相对轻松地在GPU上加速它。
我要完成的是流压缩操作,其中将仅保留非零元素。根据下面的示例代码,我大部分都在工作。我不确定如何处理的部分是在压缩发生后处理d_res中所有的额外填充空间,从而处理h_res中的所有额外填充空间。
该示例仅使用0-99序列,所有偶数项均设置为零。这只是一个例子,真正的问题将是通用的稀疏数组。
这里的答案对我有很大帮助,尽管在读取数据时,已知大小是恒定的:
How to quickly compact a sparse array with CUDA C?
我怀疑我可以通过计算d_src中0的数目来解决此问题,然后仅将d_res分配为该大小,或者在压缩后进行计数,并且仅复制那么多元素。这真的是正确的方法吗?
我觉得通过巧妙地使用迭代器或推力的其他功能,可以对此进行一些简单的修复。
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/copy.h>
//Predicate functor
struct is_not_zero
{
__host__ __device__
bool operator()(const int x)
{
return (x != 0);
}
};
using namespace std;
int main(void)
{
size_t N = 100;
//Host Vector
thrust::host_vector<int> h_src(N);
//Fill with some zero and some nonzero data, as an example
for (int i = 0; i < N; i++){
if (i % 2 == 0){
h_src[i] = 0;
}
else{
h_src[i] = i;
}
}
//Print out source data
cout << "Source:" << endl;
for (int i = 0; i < N; i++){
cout << h_src[i] << " ";
}
cout << endl;
//copies to device
thrust::device_vector<int> d_src = h_src;
//Result vector
thrust::device_vector<int> d_res(d_src.size());
//Copy non-zero elements from d_src to d_res
thrust::copy_if(d_src.begin(), d_src.end(), d_res.begin(), is_not_zero());
//Copy back to host
thrust::host_vector<int> h_res(d_res.begin(), d_res.end());
//thrust::host_vector<int> h_res = d_res; //Or just this?
//Show results
cout << "h_res size is " << h_res.size() << endl;
cout << "Result after remove:" << endl;
for (int i = 0; i < h_res.size(); i++){
cout << h_res[i] << " ";
}
cout << endl;
return 0;
}
另外,我是推力的新手,所以如果上面的代码有明显的缺陷,与推荐使用推力的做法背道而驰,请告诉我。
同样,速度总是令人感兴趣的。阅读各种推力教程中的内容,这里似乎几乎没有什么变化,并且可能会节省大量的速度或金钱。因此,请告诉我是否有一种聪明的方法来加快此速度。
最佳答案
您似乎忽略了的是copy_if
返回一个迭代器,该迭代器指向从流压缩操作复制的数据的末尾。因此,所需要做的就是:
//copies to device
thrust::device_vector<int> d_src = h_src;
//Result vector
thrust::device_vector<int> d_res(d_src.size());
//Copy non-zero elements from d_src to d_res
auto result_end = thrust::copy_if(d_src.begin(), d_src.end(), d_res.begin(), is_not_zero());
//Copy back to host
thrust::host_vector<int> h_res(d_res.begin(), result_end);
这样做的大小
h_res
仅保留非零,并且仅从流压缩的输出中复制非零。无需额外的计算。关于c++ - 用推力进行流压实;最佳做法和最快方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30691363/