Compare commits
No commits in common. "e942e957126e19a166513334db50e212c7e632c2" and "bbf0c0346f48e68b2abb10d8f3105a5879b3004a" have entirely different histories.
e942e95712
...
bbf0c0346f
@ -63,9 +63,9 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
fmt::print("Sorted {} entries within {} ms in sequential\n", dataset_seq.size(), delay_ms.count());
|
fmt::print("Sorted {} entries within {} ms in sequential\n", dataset_seq.size(), delay_ms.count());
|
||||||
|
|
||||||
|
|
||||||
const int nthreads = std::thread::hardware_concurrency();
|
static constexpr int nthreads = 16;
|
||||||
t1 = std::chrono::high_resolution_clock::now();
|
t1 = std::chrono::high_resolution_clock::now();
|
||||||
algo::MergeSort_mt::sort(dataset_par, [](int32_t a, int32_t b) {
|
algo::MergeSort_v2::sort(dataset_par.begin(), dataset_par.end(), [](int32_t a, int32_t b) {
|
||||||
return (a > b);
|
return (a > b);
|
||||||
}, nthreads);
|
}, nthreads);
|
||||||
t2 = std::chrono::high_resolution_clock::now();
|
t2 = std::chrono::high_resolution_clock::now();
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <future>
|
|
||||||
#include <ranges>
|
|
||||||
|
|
||||||
namespace algo {
|
namespace algo {
|
||||||
|
|
||||||
@ -85,43 +83,9 @@ namespace algo {
|
|||||||
|
|
||||||
class MergeSort_v2 {
|
class MergeSort_v2 {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template<typename Container, typename Comparator>
|
|
||||||
static auto
|
|
||||||
mt_merge(Container left, Container right, Comparator cmp) -> Container {
|
|
||||||
//using Iterator = typename std::iterator_traits<Container>::value_type;
|
|
||||||
|
|
||||||
Container output;
|
|
||||||
|
|
||||||
auto lefti = left.begin();
|
|
||||||
auto righti = right.begin();
|
|
||||||
|
|
||||||
while (lefti < left.end() && righti < right.end()) {
|
|
||||||
if (cmp(*lefti, *righti)) {
|
|
||||||
output.emplace_back(std::move(*lefti));
|
|
||||||
lefti++;
|
|
||||||
} else {
|
|
||||||
output.emplace_back(std::move(*righti));
|
|
||||||
righti++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (lefti < left.end()) {
|
|
||||||
output.emplace_back(std::move(*lefti));
|
|
||||||
lefti++;
|
|
||||||
}
|
|
||||||
while (righti < right.end()) {
|
|
||||||
output.emplace_back(std::move(*righti));
|
|
||||||
righti++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Iterator, typename Comparator>
|
template<typename Iterator, typename Comparator>
|
||||||
static auto
|
static auto
|
||||||
merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start,
|
merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start, std::recursive_mutex &dataset_guard) -> void {
|
||||||
std::recursive_mutex &dataset_guard) -> void {
|
|
||||||
Iterator start_m = start;
|
Iterator start_m = start;
|
||||||
Iterator begin = output_start;
|
Iterator begin = output_start;
|
||||||
Iterator start2 = middle + 1;
|
Iterator start2 = middle + 1;
|
||||||
@ -160,69 +124,6 @@ namespace algo {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container, typename Iterator, typename Comparator>
|
|
||||||
static auto mt_split(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start,
|
|
||||||
int &nthreads, std::recursive_mutex &dataset_guard, std::mutex &depth_guard) -> void {
|
|
||||||
Iterator mid = start;
|
|
||||||
Iterator to_start = output_start;
|
|
||||||
|
|
||||||
if (std::distance(start, end) < 1) {
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool rem_threads;
|
|
||||||
{
|
|
||||||
std::lock_guard guard(depth_guard); //RAII guard
|
|
||||||
rem_threads = nthreads > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rem_threads) {
|
|
||||||
{
|
|
||||||
std::lock_guard guard(depth_guard); //RAII guard
|
|
||||||
nthreads -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::advance(mid, std::distance(start, end) / 2);
|
|
||||||
std::thread t1([&]() {
|
|
||||||
mt_split(output_vec, start, mid, cmp, output_start, nthreads, dataset_guard, depth_guard);
|
|
||||||
});
|
|
||||||
|
|
||||||
std::advance(output_start, std::distance(start, mid + 1));
|
|
||||||
std::thread t2([&]() {
|
|
||||||
mt_split(output_vec, mid + 1, end, cmp, output_start, nthreads, dataset_guard, depth_guard);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//merge everything together starting from the complete beginning
|
|
||||||
t1.join();
|
|
||||||
t2.join();
|
|
||||||
std::vector<int> left;
|
|
||||||
left.assign(start, mid);
|
|
||||||
std::vector<int> right;
|
|
||||||
right.assign(mid + 1, end);
|
|
||||||
|
|
||||||
mt_merge(left, right, cmp);
|
|
||||||
} else {
|
|
||||||
//move mid iterator litterally to the mid
|
|
||||||
std::advance(mid, std::distance(start, end) / 2);
|
|
||||||
//sort the first half within an recursion
|
|
||||||
mt_split(output_vec, start, mid, cmp, output_start, nthreads, dataset_guard, depth_guard);
|
|
||||||
|
|
||||||
//move output iterator
|
|
||||||
std::advance(output_start, std::distance(start, mid + 1));
|
|
||||||
//sort the second half within a recursion
|
|
||||||
mt_split(output_vec, mid + 1, end, cmp, output_start, nthreads, dataset_guard, depth_guard);
|
|
||||||
|
|
||||||
std::vector<int> left;
|
|
||||||
left.assign(start, mid);
|
|
||||||
std::vector<int> right;
|
|
||||||
right.assign(mid + 1, end);
|
|
||||||
|
|
||||||
mt_merge(left, right, cmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Iterator, typename Comparator>
|
template<typename Container, typename Iterator, typename Comparator>
|
||||||
static auto ms_split(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start,
|
static auto ms_split(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start,
|
||||||
int &nthreads, std::recursive_mutex &dataset_guard, std::mutex &depth_guard) -> void {
|
int &nthreads, std::recursive_mutex &dataset_guard, std::mutex &depth_guard) -> void {
|
||||||
@ -241,16 +142,12 @@ namespace algo {
|
|||||||
std::advance(mid, std::distance(start, end) / 2);
|
std::advance(mid, std::distance(start, end) / 2);
|
||||||
//sort the first half within an recursion
|
//sort the first half within an recursion
|
||||||
|
|
||||||
std::thread t1([&]() {
|
std::thread t1([&]() { ms_split(output_vec, start, mid, cmp, output_start, nthreads, dataset_guard, depth_guard); });
|
||||||
ms_split(output_vec, start, mid, cmp, output_start, nthreads, dataset_guard, depth_guard);
|
|
||||||
});
|
|
||||||
|
|
||||||
//move output iteratoroutput_vec, start, mid, cmp, output_start
|
//move output iteratoroutput_vec, start, mid, cmp, output_start
|
||||||
std::advance(output_start, std::distance(start, mid + 1));
|
std::advance(output_start, std::distance(start, mid + 1));
|
||||||
//sort the second half within a recursion
|
//sort the second half within a recursion
|
||||||
std::thread t2([&]() {
|
std::thread t2([&]() { ms_split(output_vec, mid + 1, end, cmp, output_start, nthreads, dataset_guard, depth_guard); });
|
||||||
ms_split(output_vec, mid + 1, end, cmp, output_start, nthreads, dataset_guard, depth_guard);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//merge everything together starting from the complete beginning
|
//merge everything together starting from the complete beginning
|
||||||
@ -282,87 +179,8 @@ namespace algo {
|
|||||||
std::recursive_mutex dataset_guard;
|
std::recursive_mutex dataset_guard;
|
||||||
std::mutex depth_guard;
|
std::mutex depth_guard;
|
||||||
|
|
||||||
mt_split(temporary_dataset, start, end - 1, cmp, temporary_dataset.begin(), nthreads, dataset_guard,
|
ms_split(temporary_dataset, start, end - 1, cmp, temporary_dataset.begin(), nthreads, dataset_guard, depth_guard);
|
||||||
depth_guard);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MergeSort_mt {
|
|
||||||
|
|
||||||
template<typename T, typename Comparator>
|
|
||||||
static auto
|
|
||||||
merge(typename std::vector<T>::iterator mid, std::vector<T> &left, std::vector<T> &right,
|
|
||||||
Comparator cmp, std::mutex &mut) {
|
|
||||||
{
|
|
||||||
std::lock_guard lock(mut);
|
|
||||||
|
|
||||||
auto l = left.begin();
|
|
||||||
auto r = right.begin();
|
|
||||||
|
|
||||||
while (l < left.end() && r < right.end()) {
|
|
||||||
if (cmp(*l, *r)) {
|
|
||||||
*mid = *l;
|
|
||||||
l++;
|
|
||||||
} else {
|
|
||||||
*mid = *r;
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
mid++;
|
|
||||||
}
|
|
||||||
while (l < left.end()) {
|
|
||||||
*mid = *l;
|
|
||||||
mid++;
|
|
||||||
l++;
|
|
||||||
}
|
|
||||||
while (r < right.end()) {
|
|
||||||
*mid = *r;
|
|
||||||
mid++;
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename Comparator>
|
|
||||||
static auto split(std::vector<T> &data, std::vector<T> &outdata, Comparator cmp, int depth, int &num_threads, std::mutex &mut) {
|
|
||||||
if (data.size() <= 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mid = data.begin();
|
|
||||||
std::advance(mid, std::distance(data.begin(), data.end()) / 2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<T> left(std::make_move_iterator(data.begin()), std::make_move_iterator(mid));
|
|
||||||
std::vector<T> right(std::make_move_iterator(mid), std::make_move_iterator(data.end()));
|
|
||||||
|
|
||||||
if (depth < num_threads) {
|
|
||||||
std::thread left_thread([&]() { split(left, outdata, cmp, depth + 1, num_threads, mut); });
|
|
||||||
std::thread right_thread([&]() { split(right, outdata, cmp, depth + 1, num_threads, mut); });
|
|
||||||
|
|
||||||
left_thread.join();
|
|
||||||
right_thread.join();
|
|
||||||
} else {
|
|
||||||
split(left, outdata, cmp, depth + 1, num_threads, mut);
|
|
||||||
split(right, outdata, cmp, depth + 1, num_threads, mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mid = outdata.begin();
|
|
||||||
std::advance(mid, std::distance(outdata.begin(), outdata.end())/2);
|
|
||||||
merge(mid, left, right, cmp, mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<typename T, typename Comparator>
|
|
||||||
static auto
|
|
||||||
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;
|
|
||||||
|
|
||||||
split(data, local_result, cmp, 0, num_threads, local_result_lock);
|
|
||||||
data = local_result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user