Я реализовал свой собственный компаратор для STL sort
функция, которая помогает сортировать 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
Моя реализация процессора использует класс под названием 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 сделает мою работу. Однако я начал искать много реализаций, подобных описанной здесь: 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
?Thrust
не позволяй мне сделать этозаранее спасибо
я вижу, что вы пытаетесь реализовать лексикографическую технику сортировки (но я сделал это с одним огромным вектором 1D), я был там и реализовал функцию, которая сортирует векторы, но на самом деле она отстает от лексикографической сортировки В любом случае, я не уверен, смогу ли я разместить здесь код, поэтому, если вам нужна помощь, я был бы рад помочь
PS: посмотрите на реализацию lexicographic_sort.cu в коде примера тяги (я тоже его подправил, но этот тоже отстает)
Функция компаратора, которая может вам понадобиться для проверки из двух разных мест в одномерном векторе (который содержит все данные), приведена в списке (кстати, этот метод намного медленнее, чем ЦП), но кто знает, что у вас может возникнуть идея улучшить или использовать его лучше, чем я
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;
}
я нашел разумный метод, который может, наконец, побить процессор (не с точки зрения времени, но с точки зрения элементов данных)
на самом деле мой новый метод включает в себя использование thrust :: mismatch, и я прилагаю код для функции
Хорошо, что в этой версии время работы этой функции составляет около 2 мс. с очень большим количеством данных, таких как 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
это круто 🙂