Advertisement
TShiva

multithread_qsort

Nov 7th, 2017
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.44 KB | None | 0 0
  1. #include <iostream>
  2. #include <list>
  3. #include <future>
  4. #include <stack>
  5. //#include <thread>
  6. //#include <exception>
  7. //#include <mutex>
  8. //#include <memory>
  9. #include <chrono>
  10. #include <vector>
  11. #include <algorithm>
  12.  
  13.  
  14. struct empty_stack : std::exception {
  15. const char *what() const throw() {
  16. return "empty stack";
  17. }
  18. };
  19.  
  20.  
  21. template<typename T>
  22. class thread_safe_stack //реализация потокобезопасного стэка
  23. {
  24. private:
  25. std::stack<T> data;
  26. mutable std::mutex m;
  27. public:
  28. thread_safe_stack() {}
  29.  
  30. thread_safe_stack(const thread_safe_stack &other) {
  31. std::lock_guard<std::mutex> lock(other.m);
  32. data = other.data;
  33. }
  34.  
  35. thread_safe_stack &operator=(const thread_safe_stack &) = delete;
  36.  
  37. void push(T new_value) {
  38. std::lock_guard<std::mutex> lock(m);
  39. data.push(std::move(new_value));
  40. }
  41.  
  42. std::shared_ptr<T> pop() {
  43. std::lock_guard<std::mutex> lock(m);
  44. if (data.empty())
  45. return std::shared_ptr<T>();
  46. //throw empty_stack();
  47. std::shared_ptr<T> const res(
  48. std::make_shared<T>(std::move(data.top())));
  49. data.pop();
  50. return res;
  51. }
  52.  
  53. void pop(T &value) {
  54. std::lock_guard<std::mutex> lock(m);
  55. if (data.empty())
  56. //return std::shared_ptr<T>();
  57. throw empty_stack();
  58. value = std::move(data.top());
  59. data.pop();
  60. }
  61.  
  62. bool empty() const {
  63. std::lock_guard<std::mutex> lock(m);
  64. return data.empty();
  65. }
  66. };
  67.  
  68. template<typename T>
  69. struct sorter { // класс sorter объединяет стек неотсортированных блоков
  70. struct chunk_to_sort {
  71. std::list<T> data;
  72. std::promise<std::list<T>> promise;// предоставляет возможности для хранения значения, которое
  73. // позже приобрел асинхронно через std::future объекта
  74. };
  75.  
  76. thread_safe_stack<chunk_to_sort> chunks;
  77. std::vector<std::thread> threads; //
  78. unsigned const max_thread_count;
  79. std::atomic<bool> end_of_data;
  80.  
  81. sorter() :
  82. max_thread_count(std::thread::hardware_concurrency()),
  83. end_of_data(false) {}
  84.  
  85. ~sorter() {
  86. end_of_data = true;
  87. for (unsigned i = 0; i < threads.size(); ++i) {
  88. threads[i].join();
  89. }
  90. }
  91.  
  92. void try_sort_chunk() {//извлекает поток из стека
  93. std::shared_ptr<chunk_to_sort> chunk = chunks.pop();
  94. if (chunk) {
  95. sort_chunk(chunk);
  96. }
  97. }
  98.  
  99. std::list<T> do_sort(std::list<T> &chunk_data)
  100. {
  101.  
  102. {
  103. if (chunk_data.empty()) {
  104. return chunk_data;
  105. }
  106. }
  107.  
  108. std::list<T> result;
  109. result.splice(result.begin(), chunk_data, chunk_data.begin());
  110. T const &partition_val = *result.begin();
  111. typename std::list<T>::iterator divide_point =
  112. std::partition(chunk_data.begin(), chunk_data.end(),
  113. [&](T const &val) { return val < partition_val; });
  114.  
  115. chunk_to_sort new_lower_chunk;
  116. new_lower_chunk.data.splice(new_lower_chunk.data.end(),
  117. chunk_data, chunk_data.begin(),
  118. divide_point);
  119.  
  120. std::future<std::list<T> > new_lower =
  121. new_lower_chunk.promise.get_future();
  122. chunks.push(std::move(new_lower_chunk));
  123. // std::cout<<threads.size();
  124. if (threads.size() < max_thread_count) {
  125. threads.push_back(std::thread(&sorter<T>::sort_thread, this));
  126. }
  127.  
  128. std::list<T> new_higher(do_sort(chunk_data));
  129.  
  130. result.splice(result.end(), new_higher);
  131. while (new_lower.wait_for(std::chrono::seconds(0)) !=
  132. std::future_status::ready) {
  133. try_sort_chunk();
  134. }
  135.  
  136. result.splice(result.begin(), new_lower.get());
  137. return result;
  138. }
  139.  
  140. void sort_chunk(std::shared_ptr<chunk_to_sort > const& chunk)
  141. {
  142. chunk->promise.set_value(do_sort(chunk->data));
  143. }
  144.  
  145. void sort_thread()
  146. {
  147. while(!end_of_data)
  148. {
  149. try_sort_chunk();
  150. std::this_thread::yield();
  151. }
  152. }
  153.  
  154. };
  155.  
  156. template<typename T>
  157. std::list<T> parallel_quick_sort(std::list<T> input) {
  158. if (input.empty()) {
  159. return input;
  160. }
  161. sorter<T> s;
  162. return s.do_sort(input);
  163. }
  164.  
  165.  
  166. int main() {
  167. std::list<int> cocks;
  168. for(int i = 0; i<1000000; ++i){
  169. cocks.push_back(std::rand()%10);
  170. }
  171. // for(auto i:cocks ) {
  172. // std::cout << i << " ";
  173. // }
  174.  
  175. auto begin = std::chrono::high_resolution_clock::now();
  176. parallel_quick_sort(cocks);
  177. auto end = std::chrono::high_resolution_clock::now();
  178. // std::list<int> new_cocks = parallel_quick_sort(cocks);
  179. std::cout<<std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count()<<"ns"<< std::endl;
  180.  
  181. auto begin2 = std::chrono::high_resolution_clock::now();
  182. cocks.sort();
  183. auto end2 = std::chrono::high_resolution_clock::now();
  184. std::cout<<std::chrono::duration_cast<std::chrono::nanoseconds>(end2-begin2).count()<<"ns"<< std::endl;
  185.  
  186.  
  187. //
  188. //std::cout<< std::endl;
  189. // for(auto i:new_cocks ) {
  190. // std::cout << i << " ";
  191. // }
  192.  
  193.  
  194. return 0;
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement