diff --git a/task1/main.cpp b/task1/main.cpp index fbe52bc..6297ca5 100644 --- a/task1/main.cpp +++ b/task1/main.cpp @@ -44,23 +44,54 @@ auto main(int argc, char *argv[]) -> int { return -1; } - fmt::print("Opened file {} sucessfully!\n", "dummy"); + fmt::print("Opened file {} sucessfully\n", "dummy"); std::vector dataset; parse_file(file, dataset); fmt::print("Read {} values from {}\n", dataset.size(), "dummy"); - auto t1 = std::chrono::high_resolution_clock::now(); + auto dataset_par = dataset; + auto dataset_seq = dataset; - algo::MergeSort_v1::sort(dataset.begin(), dataset.end(), [](int32_t a, int32_t b) { + auto t1 = std::chrono::high_resolution_clock::now(); + algo::MergeSort_v1::sort(dataset_seq.begin(), dataset_seq.end(), [](int32_t a, int32_t b) { return (a > b); }); - auto t2 = std::chrono::high_resolution_clock::now(); - auto delay_ms = std::chrono::duration_cast(t2 - t1); - fmt::print("Sorted {} entries within {} ms.", dataset.size(), delay_ms.count()); + fmt::print("Sorted {} entries within {} ms in sequential\n", dataset_seq.size(), delay_ms.count()); + + t1 = std::chrono::high_resolution_clock::now(); + algo::MergeSort_v2::sort(dataset_par.begin(), dataset_par.end(), [](int32_t a, int32_t b) { + return (a > b); + }, 16); + t2 = std::chrono::high_resolution_clock::now(); + + delay_ms = std::chrono::duration_cast(t2 - t1); + fmt::print("Sorted {} entries within {} ms in parallel using {} threads\n", dataset_seq.size(), delay_ms.count(), 16); + + auto eq = (dataset_seq == dataset_par); + fmt::print("Equality: {}\n", eq); + fmt::print("Parallel dataset: {}; Sequential dataset: {}\n", dataset_par.size(), dataset_seq.size()); + + //fmt::print("Created {} recurstions", algo::MergeSort_v1::get_recursions()); + + std::ofstream ofile("dataset.out.dat", std::ios_base::out); + if(!ofile.is_open()) { + fmt::print("Error writing to file"); + return -1; + } + + for(auto &element : dataset_seq) { + ofile << std::to_string(element) << '\n'; + } + + file.close(); + ofile.flush(); + ofile.close(); + + fmt::print("Written to output file\n"); return 0; diff --git a/task1/mergesort.h b/task1/mergesort.h index ae90a43..18d4ef7 100644 --- a/task1/mergesort.h +++ b/task1/mergesort.h @@ -2,13 +2,16 @@ #include #include +#include +#include namespace algo { class MergeSort_v1 { private: template - static auto merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start) -> void { + static auto + merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start) -> void { Iterator start_m = start; Iterator begin = output_start; Iterator start2 = middle + 1; @@ -46,7 +49,8 @@ namespace algo { } template - static auto ms_split(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start) -> void { + static auto + ms_split(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start) -> void { Iterator mid = start; Iterator begin = output_start; @@ -77,4 +81,106 @@ namespace algo { } }; + class MergeSort_v2 { + private: + //Caution: non thread-safe, must be executed with additional protection (e.g. lock_guard) + template + static auto + merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start) -> void { + Iterator start_m = start; + Iterator begin = output_start; + Iterator start2 = middle + 1; + + //merge from input until one half completes + while (start <= middle && start2 <= end) { + if (cmp(*start, *start2)) { + *output_start = *start; + start++; + } else { + *output_start = *start2; + start2++; + } + output_start++; + } + + //try to finish first half + while (start <= middle) { + *output_start = *start; + start++; + output_start++; + } + + while (start2 <= end) { + *output_start = *start2; + start2++; + output_start++; + } + + const auto size = std::distance(start_m, end); + for (auto i = 0; i <= size; i++, start_m++, begin++) { + *start_m = *begin; + } + + } + + template + static auto ms_split(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start, + int &nthreads, std::mutex &dataset_guard, std::mutex &depth_guard) -> void { + Iterator mid = start; + Iterator begin = output_start; + + if (std::distance(start, end) < 1) { + return; + } else { + if (nthreads > 1) { + depth_guard.lock(); + nthreads -= 2; + depth_guard.unlock(); + //move mid iterator litterally to the mid + std::advance(mid, std::distance(start, end) / 2); + //sort the first half within an recursion + + std::thread t1([&]() { ms_split(output_vec, start, mid, cmp, output_start, nthreads, dataset_guard, depth_guard); }); + + //move output iteratoroutput_vec, start, mid, cmp, output_start + std::advance(output_start, std::distance(start, mid + 1)); + //sort the second half within a recursion + std::thread t2([&]() { ms_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(); + const std::lock_guard lock(dataset_guard); + merge(start, mid, end, cmp, begin); + } else { + //move mid iterator litterally to the mid + std::advance(mid, std::distance(start, end) / 2); + //sort the first half within an recursion + ms_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 + ms_split(output_vec, mid + 1, end, cmp, output_start, nthreads, dataset_guard, depth_guard); + + //merge everything together starting from the complete beginning + const std::lock_guard lock(dataset_guard); + merge(start, mid, end, cmp, begin); + } + } + } + + public: + template + static auto sort(Iterator start, Iterator end, Comparator cmp, int nthreads) -> void { + using valtype = typename std::iterator_traits::value_type; + std::vector temporary_dataset(std::distance(start, end)); + std::mutex dataset_guard; + std::mutex depth_guard; + + ms_split(temporary_dataset, start, end - 1, cmp, temporary_dataset.begin(), nthreads, dataset_guard, depth_guard); + } + }; + } \ No newline at end of file