CUDA:在 GPU 上对矢量<矢量>进行排序<int>
CUDA: Sorting a vector< vector<int> > on the GPU
我已经为STL的sort
函数实现了我自己的比较器,这有助于在CPU上对std::vector< std::vector<int> >
进行排序。用户输入std::vector< std::vector<int> >
和字符串变量,例如021
。通过使用这个字符串,排序首先在第一列上完成,然后在第三列上,然后在第二列上。例子:
1 2 3
3 2 1
1 1 1
1 1 2
假设字符串是10
输出将是
1 1 1
1 1 2
1 2 3
3 2 1
我的CPU实现使用一个叫做Sorting
的类,这个类是用下面两个文件实现的:
Sorting.h
class Sorting{
private:
public:
Sorting();
~Sorting();
std::vector<std::vector<int>> applySort(std::vector<std::vector<int>>
data,const std::string& attr);
};
Sorting.cpp
Sorting::Sorting(){}
Sorting::~Sorting(){}
std::vector<std::vector<int>> Sorting::applySort(
std::vector<std::vector<int>> data, const std::string& attr){
std::sort(data.begin(), data.begin()+data.size(), Comparator(attr));
return data;
}
Comparator.h
class Comparator{
private:
std::string attr;
public:
Comparator(const std::string& attr) { this->attr = attr; }
bool operator()(const std::vector<int>& first, const std::vector<int>&
second){
size_t i;
for(i=0;i<attr.size();i++){
if(first[attr.at(i) - '0'] < second[attr.at(i) - '0']) return true;
else if(first[attr.at(i) - '0'] > second[attr.at(i)-'0'])
return false;
}
return false;
}
};
我的实现已经经过测试,它工作正常。我有兴趣做一个类似的CUDA实现,它将利用GPU的能力,以便更快地产生输出。
最初我认为,因为我的目标是有点混乱,也许改变一个已知的实现在GPU排序会做我的工作。然而,我开始搜索许多实现,就像这里描述的那样:http://blogs.nvidia.com/2012/09/how-tesla-k20-speeds-up-quicksort-a-familiar-comp-sci-code/,这让我意识到这将是一件很难实现的事情。
我不确定这是否是最好的行动方案。我开始搜索图书馆,找到了Thrust
。然而,尽管Thrust允许您定义自己的比较器,但是在我昨天提出的一个问题中,我了解到创建host_vector < host_vector<int> >
是不可能的。
我想把向量的向量变换成一个向量对我没有多大帮助,因为我不知道如何实现比较器类。
我想听听你对这个问题的看法。
- 我该如何处理这个问题?
-
Thrust
可以实现吗? 在GPU上做它会给我的整体代码一个更好的性能吗?请注意,向量的向量可以是巨大的,数百万行,但只有几个(5-10)列。 - 是设计自己的排序还是更改已经可用的排序函数更好?虽然这听起来是个好主意,但在实践中,我觉得这需要我付出很多努力才能实现。使用一个简单的比较器和一个库中的排序函数对我来说是最好的,但是
Thrust
的限制不允许我这样做。
提前感谢
我看到你正试图实现一个字典排序技术(但我已经用一个1D巨大的向量),好吧,我一直在那里,我已经实现了一个排序向量的函数,但实际上它落后于字典排序,无论如何,我不确定我是否可以在这里发布代码,所以如果你需要任何帮助,我会很乐意帮助
PS:查看lexicographical_sort的实现。Cu在推力示例代码(我也调整了它,但那一个也落后)为了检查1D vector(包含所有数据)中的两个不同位置,您可能需要比较器函数列在下面(顺便说一下,这种技术比CPU慢得多),但谁知道您可能会想到改进它或比我更好地使用它
struct arbitrary_functor
{
template <typename Tuple> __host__ __device__
void operator()(Tuple t)
{
if(thrust::get<0>(t)>thrust::get<1>(t))
thrust::get<2>(t) = 1;
else
thrust::get<2>(t) = 0;
}
};
int checkLexo_1vec(const thrust::device_vector<char> & A, int bv1, int bv2, int N){
int i;
thrust::device_vector<char> temp(N);
thrust::device_vector<char> sum(N);
thrust::for_each(thrust::make_zip_iterator(
thrust::make_tuple(A.begin()+bv2, A.begin()+bv1,temp.begin())),
thrust::make_zip_iterator(
thrust::make_tuple(A.end()+(bv2+N),A.end()+(bv1+N), temp.end())),
arbitrary_functor());
thrust::inclusive_scan(temp.begin(),temp.end(),sum.begin());
int a = thrust::lower_bound(sum.begin(),sum.end(),1) - sum.begin();
thrust::for_each(thrust::make_zip_iterator(
thrust::make_tuple(A.begin()+bv1, A.begin()+bv2, temp.begin())),
thrust::make_zip_iterator(
thrust::make_tuple(A.end()+(bv1+N), A.end()+(bv2+N),temp.end())),
arbitrary_functor());
thrust::inclusive_scan(temp.begin(),temp.end(),sum.begin());
int b = thrust::lower_bound(sum.begin(),sum.end(),1) - sum.begin();
if(a<=b)
return 1;
else
return 0;
}
我找到了一个合理的方法,最终可以击败CPU(不是在时间方面,而是在数据元素方面)实际上,我的新方法涉及使用thrust::mismatch,并且我附加了函数
的代码这个版本的优点是这个函数的运行时间大约是2ms。有非常大量的数据,如N = 1000000 to N = 1000
,无论如何,我张贴的功能代码,让我知道,如果你发现任何用户发现一些其他的改进,可以减少整体运行时间
template<typename Ivec>
int lexoMM(Ivec vec, int bv1, int bv2, int N){
typedef thrust::device_vector<int>::iterator Iterator;
thrust::pair<Iterator,Iterator> result;
result = thrust::mismatch(vec.begin()+bv1, vec.begin()+(bv1+N-1), vec.begin()+bv2);
if(result.first == vec.end()){
//cout<<"Both are equal (right order)"<<endl;
return 1;
}
else if(result.first>result.second){
//cout<<"Wrong order"<<endl;
//cout<<*result.first<<","<<*result.second;
return 0;
}
else{
//cout<<"Right order"<<endl;
//cout<<*result.first<<","<<*result.second;
return 1;
}
}
PS:我觉得我真的浪费了我的时间来实现我自己的版本,但thrust
是很棒的:)
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中