Advertisement
Omnifarious

C++ Parallel Sort

Feb 9th, 2019
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.03 KB | None | 0 0
  1. #include <thread>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <deque>
  5. #include <random>
  6. #include <utility>
  7. #include <memory>
  8. #include <cstdint>
  9. //#include <fstream>
  10.  
  11. using vecsize_t = ::std::uint64_t;
  12. using veciter_t = ::std::uint32_t *;
  13.  
  14. void gen_and_sort_section(const veciter_t &begin, const veciter_t &end, int seed)
  15. {
  16.    ::std::minstd_rand randgen(seed);
  17.    ::std::generate(begin, end, randgen);
  18.    ::std::sort(begin, end);
  19. }
  20.  
  21. void merge_sections(const veciter_t &begin,
  22.                     const veciter_t &middle,
  23.                     const veciter_t &end,
  24.                     ::std::thread thr1,
  25.                     ::std::thread thr2)
  26. {
  27.    thr1.join();
  28.    thr2.join();
  29.    ::std::inplace_merge(begin, middle, end);
  30. }
  31.  
  32. struct sort_thread {
  33.    ::std::thread thr;
  34.    const int part_begin;
  35.    const int part_end;
  36.  
  37.    sort_thread(decltype(gen_and_sort_section) &func,
  38.                const veciter_t &begin,
  39.                const veciter_t &end,
  40.                int seed,
  41.                int part_begin,
  42.                int part_end)
  43.         : thr(func, begin, end, seed), part_begin(part_begin), part_end(part_end)
  44.    {
  45.    }
  46.    sort_thread(decltype(merge_sections) &func,
  47.                const veciter_t &begin,
  48.                const veciter_t &middle,
  49.                const veciter_t &end,
  50.                ::std::thread thr1,
  51.                ::std::thread thr2,
  52.                int part_begin,
  53.                int part_end)
  54.         : thr(func, begin, middle, end, ::std::move(thr1), ::std::move(thr2)),
  55.           part_begin(part_begin), part_end(part_end)
  56.    {
  57.    }
  58. };
  59.  
  60. int main()
  61. {
  62.    using ::std::thread;
  63.    using ::std::unique_ptr;
  64.    using ::std::make_unique;
  65.    using ::std::uint32_t;
  66.  
  67.    constexpr auto size = 1ULL << 31;
  68.    auto huge_array = make_unique<uint32_t[]>(size);
  69.    const int cpucount = ::std::max(thread::hardware_concurrency() / 2, 1U);
  70.    const int sections = cpucount;
  71.    const int secmarkers = sections + 1;
  72.    auto partitions = make_unique<veciter_t[]>(secmarkers);
  73.  
  74.    partitions[0] = &(huge_array[0]);
  75.    for (int i = 1; i < secmarkers; ++i) {
  76.       auto const prev_part = partitions[i - 1];
  77.       auto const remaining = secmarkers - i;
  78.       partitions[i] = prev_part + (&(huge_array[size]) - prev_part) / remaining;
  79.    }
  80.    if (partitions[secmarkers - 1] != &(huge_array[size])) {
  81.       return 1;
  82.    }
  83.  
  84.    ::std::random_device seedmaker;
  85.    ::std::deque<sort_thread> rthreads;
  86.    for (int i = 0; i < sections; ++i)
  87.    {
  88.       rthreads.emplace_back(
  89.          gen_and_sort_section, partitions[i], partitions[i + 1], seedmaker(),
  90.          i, i + 1
  91.          );
  92.    }
  93.    while (rthreads.size() >= 2) {
  94.       if (rthreads.front().part_end >= sections) {
  95.          rthreads.emplace_back(::std::move(rthreads.front()));
  96.          rthreads.pop_front();
  97.       } else {
  98.          auto thr1{::std::move(rthreads.front())};
  99.          rthreads.pop_front();
  100.          auto thr2{::std::move(rthreads.front())};
  101.          rthreads.pop_front();
  102.          if (thr1.part_end != thr2.part_begin) {
  103.             return 2;
  104.          } else {
  105.             rthreads.emplace_back(merge_sections,
  106.                                   partitions[thr1.part_begin],
  107.                                   partitions[thr1.part_end],
  108.                                   partitions[thr2.part_end],
  109.                                   ::std::move(thr1.thr),
  110.                                   ::std::move(thr2.thr),
  111.                                   thr1.part_begin,
  112.                                   thr2.part_end);
  113.          }
  114.       }
  115.    }
  116.    if (rthreads.front().part_begin != 0) {
  117.       return 3;
  118.    } else if (rthreads.front().part_end != sections) {
  119.       return 4;
  120.    } else {
  121.       rthreads.front().thr.join();
  122.    }
  123.    /*
  124.    {
  125.       ::std::ofstream of("/proc/self/fd/1");
  126.  
  127.       of << huge_array[0] << '\n';
  128.       for (vecsize_t i = 1; i < huge_array.size(); ++i) {
  129.          if (huge_array[i] < huge_array[i - 1]) {
  130.             return 5;
  131.          }
  132.          of << huge_array[i] << '\n';
  133.       }
  134.    }
  135.    */
  136.    return 0;
  137. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement