#include <ctime> #include <iostream> #include <functional> #include <stack> #include <algorithm> #include <process.h> #include <windows.h> inline void generate(int *a, int size, int seed = 0) { int i; srand(seed); for (i = 0; i < size; ++i) { a[i] = rand(); } } inline int get_processor_cnt() { SYSTEM_INFO info; GetSystemInfo(&info); return info.dwNumberOfProcessors; } inline std::pair<int*, int*>* new_range(int *first, int *last) { return new std::pair<int*, int*>(first, last); } inline void get_range(int *&first, int *&last, void *range) { first = ((std::pair<int*, int*>*)range)->first; last = ((std::pair<int*, int*>*)range)->second; delete range; } int g_thread_cnt, g_processor_cnt; CRITICAL_SECTION g_thread_cnt_cs; HANDLE g_finish; inline bool get_thread() { bool success = false; EnterCriticalSection(&g_thread_cnt_cs); if (g_thread_cnt) { --g_thread_cnt; success = true; } LeaveCriticalSection(&g_thread_cnt_cs); return success; } inline void release_thread() { bool finish = false; EnterCriticalSection(&g_thread_cnt_cs); if (++g_thread_cnt == g_processor_cnt) finish = true; LeaveCriticalSection(&g_thread_cnt_cs); if (finish) SetEvent(g_finish); } inline void iter_sort(int *a, int *b) { if (*b < *a) std::iter_swap(a, b); } inline void iter_sort(int *a, int *b, int *c) { iter_sort(a, b); iter_sort(b, c); iter_sort(a, b); } void partition(int *&l_last, int *&r_first, int *first, int *last) { int *left, *l_equal, *right, *r_equal; left = l_equal = first - 1; right = r_equal = --last; int pivot = *last; while (true) { while (*++left < pivot); while (*--right > pivot); if (right <= left) break; std::iter_swap(left, right); if (*left == pivot) std::iter_swap(left, ++l_equal); if (*right == pivot) std::iter_swap(right, --r_equal); } if (left == right) { ++left; --right; } ++l_equal; while (first != l_equal) { std::iter_swap(first++, right--); } --r_equal; while (last != r_equal) { std::iter_swap(last--, left++); } l_last = ++right; r_first = left; } void psort(void *range) { int *first, *last; get_range(first, last, range); std::stack<int*> stk; stk.push(first); stk.push(last); int *tmp_a, *tmp_b; while (stk.size()) { last = stk.top(); stk.pop(); first = stk.top(); stk.pop(); if (last - first < 2) continue; if (stk.size() > 2 && get_thread()) { _beginthread(psort, 0, new_range(first, last)); continue; } iter_sort(first, tmp_a = first + (last - first >> 1), tmp_b = last - 1); std::iter_swap(tmp_a, tmp_b); partition(tmp_a, tmp_b, first, last); stk.push(first); stk.push(tmp_a); stk.push(tmp_b); stk.push(last); } release_thread(); } inline void parallel_sort(int *first, int *last) { g_processor_cnt = get_processor_cnt(); g_thread_cnt = g_processor_cnt - 1; g_finish = CreateEvent(NULL, true, false, NULL); InitializeCriticalSection(&g_thread_cnt_cs); psort(new_range(first, last)); WaitForSingleObject(g_finish, INFINITE); CloseHandle(g_finish); DeleteCriticalSection(&g_thread_cnt_cs); } #define SIZE 30000000 int src[SIZE]; int ss_res[SIZE]; int ps_res[SIZE]; int main() { generate(src, SIZE); std::copy(src, src + SIZE, ss_res); std::copy(src, src + SIZE, ps_res); clock_t t = clock(); std::sort(ss_res, ss_res + SIZE); printf("%dms/n", clock() - t); t = clock(); parallel_sort(ps_res, ps_res + SIZE); printf("%dms/n", clock() - t); if (std::equal(ss_res, ss_res + SIZE, ps_res)) puts("CORRECT"); else puts("WRONG"); return 0; }