00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef _GLIBCXX_PARALLEL_QUICKSORT_H
00039 #define _GLIBCXX_PARALLEL_QUICKSORT_H 1
00040
00041 #include <parallel/parallel.h>
00042 #include <parallel/partition.h>
00043
00044 namespace __gnu_parallel
00045 {
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 template<typename RandomAccessIterator, typename Comparator>
00056 typename std::iterator_traits<RandomAccessIterator>::difference_type
00057 parallel_sort_qs_divide(RandomAccessIterator begin,
00058 RandomAccessIterator end,
00059 Comparator comp, typename std::iterator_traits
00060 <RandomAccessIterator>::difference_type pivot_rank,
00061 typename std::iterator_traits
00062 <RandomAccessIterator>::difference_type
00063 num_samples, thread_index_t num_threads)
00064 {
00065 typedef std::iterator_traits<RandomAccessIterator> traits_type;
00066 typedef typename traits_type::value_type value_type;
00067 typedef typename traits_type::difference_type difference_type;
00068
00069 difference_type n = end - begin;
00070 num_samples = std::min(num_samples, n);
00071
00072
00073 value_type* samples =
00074 static_cast<value_type*>(::operator new(num_samples
00075 * sizeof(value_type)));
00076
00077 for (difference_type s = 0; s < num_samples; ++s)
00078 {
00079 const unsigned long long index = static_cast<unsigned long long>(s)
00080 * n / num_samples;
00081 ::new(&(samples[s])) value_type(begin[index]);
00082 }
00083
00084 __gnu_sequential::sort(samples, samples + num_samples, comp);
00085
00086 value_type& pivot = samples[pivot_rank * num_samples / n];
00087
00088 __gnu_parallel::binder2nd<Comparator, value_type, value_type, bool>
00089 pred(comp, pivot);
00090 difference_type split = parallel_partition(begin, end, pred, num_threads);
00091
00092 ::operator delete(samples);
00093
00094 return split;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104 template<typename RandomAccessIterator, typename Comparator>
00105 void
00106 parallel_sort_qs_conquer(RandomAccessIterator begin,
00107 RandomAccessIterator end,
00108 Comparator comp,
00109 thread_index_t num_threads)
00110 {
00111 typedef std::iterator_traits<RandomAccessIterator> traits_type;
00112 typedef typename traits_type::value_type value_type;
00113 typedef typename traits_type::difference_type difference_type;
00114
00115 if (num_threads <= 1)
00116 {
00117 __gnu_sequential::sort(begin, end, comp);
00118 return;
00119 }
00120
00121 difference_type n = end - begin, pivot_rank;
00122
00123 if (n <= 1)
00124 return;
00125
00126 thread_index_t num_threads_left;
00127
00128 if ((num_threads % 2) == 1)
00129 num_threads_left = num_threads / 2 + 1;
00130 else
00131 num_threads_left = num_threads / 2;
00132
00133 pivot_rank = n * num_threads_left / num_threads;
00134
00135 difference_type split =
00136 parallel_sort_qs_divide(begin, end, comp, pivot_rank,
00137 _Settings::get().sort_qs_num_samples_preset,
00138 num_threads);
00139
00140 #pragma omp parallel sections
00141 {
00142 #pragma omp section
00143 parallel_sort_qs_conquer(begin, begin + split,
00144 comp, num_threads_left);
00145 #pragma omp section
00146 parallel_sort_qs_conquer(begin + split, end,
00147 comp, num_threads - num_threads_left);
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 template<typename RandomAccessIterator, typename Comparator>
00162 void
00163 parallel_sort_qs(RandomAccessIterator begin,
00164 RandomAccessIterator end,
00165 Comparator comp, typename std::iterator_traits
00166 <RandomAccessIterator>::difference_type n,
00167 int num_threads)
00168 {
00169 _GLIBCXX_CALL(n)
00170
00171 typedef std::iterator_traits<RandomAccessIterator> traits_type;
00172 typedef typename traits_type::value_type value_type;
00173 typedef typename traits_type::difference_type difference_type;
00174
00175 if (n == 0)
00176 return;
00177
00178
00179 if (num_threads > n)
00180 num_threads = static_cast<thread_index_t>(n);
00181
00182
00183 omp_set_num_threads(num_threads);
00184
00185 parallel_sort_qs_conquer(begin, begin + n, comp, num_threads);
00186 }
00187
00188 }
00189
00190 #endif