FEATURE: fully support of untuned parallel algorithm

This commit is contained in:
Robin Dietzel 2023-11-02 22:10:09 +01:00
parent 038ef8f439
commit 12f71c5d7e

View File

@ -292,42 +292,50 @@ namespace algo {
template<typename T, typename Comparator> template<typename T, typename Comparator>
static auto static auto
merge(typename std::vector<T>::iterator mid, std::vector<T> &left, std::vector<T> &right, merge(std::vector<T> left, std::vector<T> right,
Comparator cmp, std::mutex &mut) { Comparator cmp, std::mutex &mut) -> std::vector<T> {
std::vector<T> output;
output.reserve(left.size() + right.size());
auto l = left.begin(); auto l = left.begin();
auto r = right.begin(); auto r = right.begin();
auto o = output.begin();
while (l < left.end() && r < right.end()) { while (l < left.end() && r < right.end()) {
if (cmp(*l, *r)) { if (cmp(*l, *r)) {
*mid = *l; output.insert(o, *l);
l++; l++;
} else { } else {
*mid = *r; output.insert(o, *r);
r++; r++;
} }
mid++; o++;
} }
while (l < left.end()) { while (l < left.end()) {
*mid = *l; output.insert(o, *l);
mid++; o++;
l++; l++;
} }
while (r < right.end()) { while (r < right.end()) {
*mid = *r; output.insert(o, *r);
mid++; o++;
r++; r++;
} }
return output;
} }
template<typename T, typename Comparator> template<typename T, typename Comparator>
static auto split(std::vector<T> &data, std::vector<T> &output, Comparator cmp, int depth, int &num_threads, static auto split(std::vector<T> data, Comparator cmp, int depth, int &num_threads,
std::mutex &mut) { std::mutex &mut) -> std::vector<T>{
if (data.size() <= 1) { if (data.size() <= 1) {
return; return data;
} }
std::vector<T> output;
output.reserve(data.size());
auto mid = data.begin(); auto mid = data.begin();
std::advance(mid, std::distance(data.begin(), data.end()) / 2); std::advance(mid, std::distance(data.begin(), data.end()) / 2);
@ -336,43 +344,29 @@ namespace algo {
std::vector<T> right(mid, data.end()); std::vector<T> right(mid, data.end());
if (depth < num_threads) { if (depth < num_threads) {
std::thread left_thread([&]() { split(left, output, cmp, depth + 1, num_threads, mut); }); std::thread left_thread([&]() { left = split(left, cmp, depth + 1, num_threads, mut); });
std::thread right_thread([&]() { split(right, output, cmp, depth + 1, num_threads, mut); }); std::thread right_thread([&]() { right = split(right, cmp, depth + 1, num_threads, mut); });
left_thread.join(); left_thread.join();
right_thread.join(); right_thread.join();
} else { } else {
split(left, output, cmp, depth + 1, num_threads, mut); left = split(left, cmp, depth + 1, num_threads, mut);
split(right, output, cmp, depth + 1, num_threads, mut); right = split(right, cmp, depth + 1, num_threads, mut);
} }
return merge(left, right, cmp, mut);
mid = output.begin();
std::advance(mid, std::distance(output.begin(), output.end()) / 2);
std::vector<T> buf;
buf.reserve(data.size());
merge(buf.begin(), left, right, cmp, mut);
{
std::lock_guard lock(mut);
auto bufi = buf.begin();
for(auto &element : output) {
element = *bufi;
bufi++;
}
}
} }
public: public:
template<typename T, typename Comparator> template<typename T, typename Comparator>
static auto static auto
sort(std::vector<T> &data, Comparator cmp, int num_threads = std::thread::hardware_concurrency()) -> void { sort(std::vector<T> &data, Comparator cmp, int num_threads = std::thread::hardware_concurrency()) -> void {
std::vector<T> local_result = data;
std::mutex local_result_lock; std::mutex local_result_lock;
std::vector<T> output;
output.reserve(data.size());
split(data, local_result, cmp, 0, num_threads, local_result_lock); output = split(data, cmp, 0, num_threads, local_result_lock);
data = local_result; data.assign(output.begin(), output.end());
} }
}; };
} }