diff --git a/libstdc++-v3/doc/xml/manual/parallel_mode.xml b/libstdc++-v3/doc/xml/manual/parallel_mode.xml index fb439062feaa2dc1f1ac686198aa0e911b46e990..faea5a9e7f68cac79774e49057841a305865904d 100644 --- a/libstdc++-v3/doc/xml/manual/parallel_mode.xml +++ b/libstdc++-v3/doc/xml/manual/parallel_mode.xml @@ -575,24 +575,36 @@ This means that the actual parallelization strategy is chosen at run-time. (Choosing the variants at compile-time will come soon.) </para> +<para> +For the following algorithms in general, we have +<code>__gnu_parallel::parallel_tag</code> and +<code>__gnu_parallel::default_parallel_tag</code>, in addition to +<code>__gnu_parallel::sequential_tag</code>. +<code>__gnu_parallel::default_parallel_tag</code> chooses the default +algorithm at compiletime, as does omitting the tag. +<code>__gnu_parallel::parallel_tag</code> postpones the decision to runtime +(see next section). +For all tags, the number of threads desired for this call can optionally be +passed to the respective tag's constructor. +</para> + +<para> +The <code>multiway_merge</code> algorithm comes with the additional choices, +<code>__gnu_parallel::exact_tag</code> and +<code>__gnu_parallel::sampling_tag</code>. +Exact and sampling are the two available splitting strategies. +</para> + <para> For the <code>sort</code> and <code>stable_sort</code> algorithms, there are -several possible choices, -<code>__gnu_parallel::parallel_tag</code>, -<code>__gnu_parallel::default_parallel_tag</code>, +several additional choices, namely <code>__gnu_parallel::multiway_mergesort_tag</code>, <code>__gnu_parallel::multiway_mergesort_exact_tag</code>, <code>__gnu_parallel::multiway_mergesort_sampling_tag</code>, -<code>__gnu_parallel::quicksort_tag</code>, +<code>__gnu_parallel::quicksort_tag</code>, and <code>__gnu_parallel::balanced_quicksort_tag</code>. -Multiway mergesort comes with two splitting strategies for merging, therefore -the extra choice. If non is chosen, the default splitting strategy is selected. -<code>__gnu_parallel::default_parallel_tag</code> chooses the default parallel -sorting algorithm at runtime. <code>__gnu_parallel::parallel_tag</code> -postpones the decision to runtime (see next section). -The quicksort options cannot be used for <code>stable_sort</code>. -For all tags, the number of threads desired for this call can optionally be -passed to the tag's constructor. +Multiway mergesort comes with the two splitting strategies for multi-way +merging. The quicksort options cannot be used for <code>stable_sort</code>. </para> </sect3> diff --git a/libstdc++-v3/include/parallel/merge.h b/libstdc++-v3/include/parallel/merge.h index cabd5bd4de2ec598f6de8e8307c88256fff6d8fd..580b1479329e14fbab6808a5c2141b994c903b9a 100644 --- a/libstdc++-v3/include/parallel/merge.h +++ b/libstdc++-v3/include/parallel/merge.h @@ -254,11 +254,11 @@ namespace __gnu_parallel RandomAccessIterator3 target_end = parallel_multiway_merge < /* stable = */ true, /* sentinels = */ false>( - seqs, seqs + 2, target, comp, + seqs, seqs + 2, target, multiway_merge_exact_splitting < /* stable = */ true, iterator_pair*, Comparator, difference_type1>, - max_length); + max_length, comp, omp_get_max_threads()); return target_end; } diff --git a/libstdc++-v3/include/parallel/multiway_merge.h b/libstdc++-v3/include/parallel/multiway_merge.h index 37e99cdeb6a9adfdeacef3dac17ae99da9b61754..3c75c70f3c4eb60b64bd8ea2f920883fe472a79e 100644 --- a/libstdc++-v3/include/parallel/multiway_merge.h +++ b/libstdc++-v3/include/parallel/multiway_merge.h @@ -297,7 +297,7 @@ template<template<typename RAI, typename C> class iterator, RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { _GLIBCXX_CALL(length); @@ -416,7 +416,7 @@ template<template<typename RAI, typename C> class iterator, multiway_merge_4_variant(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { _GLIBCXX_CALL(length); typedef _DifferenceTp difference_type; @@ -540,8 +540,7 @@ template<typename LT, multiway_merge_loser_tree(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, - _DifferenceTp length) + _DifferenceTp length, Comparator comp) { _GLIBCXX_CALL(length) @@ -626,8 +625,8 @@ template<typename LT, const typename std::iterator_traits<typename std::iterator_traits< RandomAccessIteratorIterator>::value_type::first_type>::value_type& sentinel, - Comparator comp, - _DifferenceTp length) + _DifferenceTp length, + Comparator comp) { _GLIBCXX_CALL(length) typedef _DifferenceTp difference_type; @@ -716,8 +715,8 @@ template< const typename std::iterator_traits<typename std::iterator_traits< RandomAccessIteratorIterator>::value_type::first_type>::value_type& sentinel, - Comparator comp, - _DifferenceTp length) + _DifferenceTp length, + Comparator comp) { _GLIBCXX_CALL(length) @@ -740,7 +739,7 @@ template< target_end = multiway_merge_loser_tree_unguarded <UnguardedLoserTree> - (seqs_begin, seqs_end, target, sentinel, comp, length); + (seqs_begin, seqs_end, target, sentinel, length, comp); #if _GLIBCXX_ASSERTIONS _GLIBCXX_PARALLEL_ASSERT(target_end == target + length); @@ -808,10 +807,10 @@ struct multiway_merge_3_variant_sentinel_switch RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { return multiway_merge_3_variant<guarded_iterator>( - seqs_begin, seqs_end, target, comp, length); + seqs_begin, seqs_end, target, length, comp); } }; @@ -833,10 +832,10 @@ struct multiway_merge_3_variant_sentinel_switch RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { return multiway_merge_3_variant<unguarded_iterator>( - seqs_begin, seqs_end, target, comp, length); + seqs_begin, seqs_end, target, length, comp); } }; @@ -857,10 +856,10 @@ struct multiway_merge_4_variant_sentinel_switch RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { return multiway_merge_4_variant<guarded_iterator>( - seqs_begin, seqs_end, target, comp, length); + seqs_begin, seqs_end, target, length, comp); } }; @@ -882,10 +881,10 @@ struct multiway_merge_4_variant_sentinel_switch RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { return multiway_merge_4_variant<unguarded_iterator>( - seqs_begin, seqs_end, target, comp, length); + seqs_begin, seqs_end, target, length, comp); } }; @@ -908,7 +907,7 @@ struct multiway_merge_k_variant_sentinel_switch const typename std::iterator_traits<typename std::iterator_traits< RandomAccessIteratorIterator>::value_type::first_type>::value_type& sentinel, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { typedef typename std::iterator_traits<RandomAccessIteratorIterator> ::value_type::first_type @@ -921,7 +920,7 @@ struct multiway_merge_k_variant_sentinel_switch loser_tree_traits<value_type>::use_pointer , LoserTreePointerUnguarded<stable, value_type, Comparator> , LoserTreeUnguarded<stable, value_type, Comparator> - >::__type>(seqs_begin, seqs_end, target, sentinel, comp, length); + >::__type>(seqs_begin, seqs_end, target, sentinel, length, comp); } }; @@ -945,7 +944,7 @@ struct multiway_merge_k_variant_sentinel_switch const typename std::iterator_traits<typename std::iterator_traits< RandomAccessIteratorIterator>::value_type::first_type>::value_type& sentinel, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { typedef typename std::iterator_traits<RandomAccessIteratorIterator> ::value_type::first_type @@ -958,7 +957,7 @@ struct multiway_merge_k_variant_sentinel_switch loser_tree_traits<value_type>::use_pointer , LoserTreePointer<stable, value_type, Comparator> , LoserTree<stable, value_type, Comparator> - >::__type >(seqs_begin, seqs_end, target, comp, length); + >::__type >(seqs_begin, seqs_end, target, length, comp); } }; @@ -990,7 +989,7 @@ template< const typename std::iterator_traits<typename std::iterator_traits< RandomAccessIteratorIterator>::value_type::first_type>::value_type& sentinel, - Comparator comp, _DifferenceTp length) + _DifferenceTp length, Comparator comp) { _GLIBCXX_CALL(length) @@ -1043,7 +1042,7 @@ template< , RandomAccessIteratorIterator , RandomAccessIterator3 , _DifferenceTp - , Comparator>()(seqs_begin, seqs_end, target, comp, length); + , Comparator>()(seqs_begin, seqs_end, target, length, comp); break; case 4: return_target = multiway_merge_4_variant_sentinel_switch< @@ -1051,7 +1050,7 @@ template< , RandomAccessIteratorIterator , RandomAccessIterator3 , _DifferenceTp - , Comparator>()(seqs_begin, seqs_end, target, comp, length); + , Comparator>()(seqs_begin, seqs_end, target, length, comp); break; default: return_target = multiway_merge_k_variant_sentinel_switch< @@ -1060,8 +1059,7 @@ template< , RandomAccessIteratorIterator , RandomAccessIterator3 , _DifferenceTp - , Comparator>() - (seqs_begin, seqs_end, target, sentinel, comp, length); + , Comparator>()(seqs_begin, seqs_end, target, sentinel, length, comp); break; } #if _GLIBCXX_ASSERTIONS @@ -1108,8 +1106,7 @@ template< void multiway_merge_sampling_splitting( RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, - Comparator comp, difference_type length, - difference_type total_length, + difference_type length, difference_type total_length, Comparator comp, std::vector<std::pair<difference_type, difference_type> > *pieces) { typedef typename std::iterator_traits<RandomAccessIteratorIterator> @@ -1190,9 +1187,7 @@ template< void multiway_merge_exact_splitting( RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, - Comparator comp, - difference_type length, - difference_type total_length, + difference_type length, difference_type total_length, Comparator comp, std::vector<std::pair<difference_type, difference_type> > *pieces) { typedef typename std::iterator_traits<RandomAccessIteratorIterator> @@ -1297,9 +1292,10 @@ template< parallel_multiway_merge(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, - Comparator comp, Splitter splitter, - _DifferenceTp length) + _DifferenceTp length, + Comparator comp, + thread_index_t num_threads) { #if _GLIBCXX_ASSERTIONS _GLIBCXX_PARALLEL_ASSERT(seqs_end - seqs_begin > 1); @@ -1347,8 +1343,8 @@ template< std::vector<std::pair<difference_type, difference_type> >* pieces; - thread_index_t num_threads = static_cast<thread_index_t> - (std::min<difference_type>(get_max_threads(), total_length)); + num_threads = static_cast<thread_index_t> + (std::min<difference_type>(num_threads, total_length)); # pragma omp parallel num_threads (num_threads) { @@ -1365,8 +1361,8 @@ template< __gnu_parallel::_Settings::get().merge_oversampling * num_threads; - splitter(ne_seqs, ne_seqs + k, comp, length, total_length, - pieces); + splitter(ne_seqs, ne_seqs + k, length, total_length, + comp, pieces); } //single thread_index_t iam = omp_get_thread_num(); @@ -1389,7 +1385,7 @@ template< if(length > target_position) sequential_multiway_merge<stable, sentinels>( chunks, chunks + k, target + target_position, - *(seqs_begin->second), comp, length - target_position); + *(seqs_begin->second), length - target_position, comp); delete[] chunks; } // parallel @@ -1481,6 +1477,7 @@ template< * * @return end iterator of output sequence */ +// multiway_merge // public interface template< typename RandomAccessIteratorPairIterator @@ -1491,49 +1488,7 @@ RandomAccessIteratorOut multiway_merge(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length) -{ - typedef _DifferenceTp difference_type; - _GLIBCXX_CALL(seqs_end - seqs_begin) - - // catch special case: no sequences - if (seqs_begin == seqs_end) - return target; - - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((seqs_end - seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((seqs_end - seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((sequence_index_t)length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* stable = */ false, /* sentinels = */ false> - (seqs_begin, seqs_end, target, comp, - multiway_merge_sampling_splitting</* stable = */ false, - typename std::iterator_traits<RandomAccessIteratorPairIterator> - ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); - else - return sequential_multiway_merge - </* stable = */false, /* sentinels = */ false>( - seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); -} - -// public interface -template< - typename RandomAccessIteratorPairIterator - , typename RandomAccessIteratorOut - , typename _DifferenceTp - , typename Comparator> -RandomAccessIteratorOut -multiway_merge(RandomAccessIteratorPairIterator seqs_begin - , RandomAccessIteratorPairIterator seqs_end - , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length + , _DifferenceTp length, Comparator comp , __gnu_parallel::sequential_tag) { typedef _DifferenceTp difference_type; @@ -1546,10 +1501,10 @@ multiway_merge(RandomAccessIteratorPairIterator seqs_begin // Execute multiway merge *sequentially*. return sequential_multiway_merge </* stable = */ false, /* sentinels = */ false> - (seqs_begin, seqs_end, target, *(seqs_begin->second), comp, length); + (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp); } -//public interface +// public interface template< typename RandomAccessIteratorPairIterator , typename RandomAccessIteratorOut @@ -1559,8 +1514,8 @@ RandomAccessIteratorOut multiway_merge(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length - , __gnu_parallel::exact_tag) + , _DifferenceTp length, Comparator comp + , __gnu_parallel::exact_tag tag) { typedef _DifferenceTp difference_type; _GLIBCXX_CALL(seqs_end - seqs_begin) @@ -1580,17 +1535,15 @@ multiway_merge(RandomAccessIteratorPairIterator seqs_begin __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) return parallel_multiway_merge </* stable = */ false, /* sentinels = */ false>( - seqs_begin, seqs_end, - target, comp, + seqs_begin, seqs_end, target, multiway_merge_exact_splitting</* stable = */ false, typename std::iterator_traits<RandomAccessIteratorPairIterator> ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); + static_cast<difference_type>(length), comp, tag.get_num_threads()); else return sequential_multiway_merge </* stable = */ false, /* sentinels = */ false>( - seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); + seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp); } // public interface @@ -1600,10 +1553,11 @@ template< , typename _DifferenceTp , typename Comparator> RandomAccessIteratorOut -stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin +multiway_merge(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length) + , _DifferenceTp length, Comparator comp + , __gnu_parallel::sampling_tag tag) { typedef _DifferenceTp difference_type; _GLIBCXX_CALL(seqs_end - seqs_begin) @@ -1618,24 +1572,59 @@ stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin if ((seqs_end - seqs_begin > 1) && _GLIBCXX_PARALLEL_CONDITION( ((seqs_end - seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) && ((sequence_index_t)length >= __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) return parallel_multiway_merge - </* stable = */ true, /* sentinels = */ false>( + </* stable = */ false, /* sentinels = */ false>( seqs_begin, seqs_end, - target, comp, - multiway_merge_sampling_splitting</* stable = */ true, + target, + multiway_merge_exact_splitting</* stable = */ false, typename std::iterator_traits<RandomAccessIteratorPairIterator> ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); + static_cast<difference_type>(length), comp, tag.get_num_threads()); else return sequential_multiway_merge - </* stable = */ true, /* sentinels = */ false>( + </* stable = */ false, /* sentinels = */ false>( seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); + target, *(seqs_begin->second), length, comp); } +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +multiway_merge(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , parallel_tag tag = parallel_tag(0)) +{ + return multiway_merge(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +multiway_merge(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , default_parallel_tag tag) +{ + return multiway_merge(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); +} + +// stable_multiway_merge // public interface template< typename RandomAccessIteratorPairIterator @@ -1646,7 +1635,7 @@ RandomAccessIteratorOut stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length + , _DifferenceTp length, Comparator comp , __gnu_parallel::sequential_tag) { typedef _DifferenceTp difference_type; @@ -1659,7 +1648,7 @@ stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin // Execute multiway merge *sequentially*. return sequential_multiway_merge </* stable = */ true, /* sentinels = */ false> - (seqs_begin, seqs_end, target, *(seqs_begin->second), comp, length); + (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp); } // public interface @@ -1672,8 +1661,8 @@ RandomAccessIteratorOut stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length - , __gnu_parallel::exact_tag) + , _DifferenceTp length, Comparator comp + , __gnu_parallel::exact_tag tag) { typedef _DifferenceTp difference_type; _GLIBCXX_CALL(seqs_end - seqs_begin) @@ -1694,17 +1683,95 @@ stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin return parallel_multiway_merge </* stable = */ true, /* sentinels = */ false>( seqs_begin, seqs_end, - target, comp, - multiway_merge_exact_splitting - </* stable = */ true, - typename std::iterator_traits<RandomAccessIteratorPairIterator> - ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); + target, + multiway_merge_exact_splitting</* stable = */ true, + typename std::iterator_traits<RandomAccessIteratorPairIterator> + ::value_type*, Comparator, _DifferenceTp>, + static_cast<difference_type>(length), comp, tag.get_num_threads()); else return sequential_multiway_merge</* stable = */ true, /* sentinels = */ false>( seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); + target, *(seqs_begin->second), length, comp); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , sampling_tag tag) +{ + typedef _DifferenceTp difference_type; + _GLIBCXX_CALL(seqs_end - seqs_begin) + + // catch special case: no sequences + if (seqs_begin == seqs_end) + return target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((seqs_end - seqs_begin > 1) && + _GLIBCXX_PARALLEL_CONDITION( + ((seqs_end - seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((sequence_index_t)length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge + </* stable = */ true, /* sentinels = */ false>( + seqs_begin, seqs_end, + target, + multiway_merge_sampling_splitting</* stable = */ true, + typename std::iterator_traits<RandomAccessIteratorPairIterator> + ::value_type*, Comparator, _DifferenceTp>, + static_cast<difference_type>(length), comp, tag.get_num_threads()); + else + return sequential_multiway_merge + </* stable = */ true, /* sentinels = */ false>( + seqs_begin, seqs_end, + target, *(seqs_begin->second), length, comp); +} + + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , parallel_tag tag = parallel_tag(0)) +{ + return stable_multiway_merge(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , default_parallel_tag tag) +{ + return stable_multiway_merge(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); } /** @@ -1782,6 +1849,7 @@ stable_multiway_merge(RandomAccessIteratorPairIterator seqs_begin * * @return end iterator of output sequence */ +// multiway_merge_sentinels // public interface template< typename RandomAccessIteratorPairIterator @@ -1792,50 +1860,7 @@ RandomAccessIteratorOut multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length) -{ - typedef _DifferenceTp difference_type; - _GLIBCXX_CALL(seqs_end - seqs_begin) - - // catch special case: no sequences - if (seqs_begin == seqs_end) - return target; - - // Execute merge; maybe parallel, depending on the number of merged - // elements and the number of sequences and global thresholds in - // Settings. - if ((seqs_end - seqs_begin > 1) && - _GLIBCXX_PARALLEL_CONDITION( - ((seqs_end - seqs_begin) >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_k) - && ((sequence_index_t)length >= - __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) - return parallel_multiway_merge - </* stable = */ false, /* sentinels = */ true> - (seqs_begin, seqs_end, target, comp, - multiway_merge_sampling_splitting - </* stable = */ false, - typename std::iterator_traits<RandomAccessIteratorPairIterator> - ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); - else - return sequential_multiway_merge - </* stable = */false, /* sentinels = */ true>( - seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); -} - -//public interface -template< - typename RandomAccessIteratorPairIterator - , typename RandomAccessIteratorOut - , typename _DifferenceTp - , typename Comparator> -RandomAccessIteratorOut -multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin - , RandomAccessIteratorPairIterator seqs_end - , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length + , _DifferenceTp length, Comparator comp , __gnu_parallel::sequential_tag) { typedef _DifferenceTp difference_type; @@ -1848,7 +1873,8 @@ multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin // Execute multiway merge *sequentially*. return sequential_multiway_merge </* stable = */ false, /* sentinels = */ true> - (seqs_begin, seqs_end, target, *(seqs_begin->second), comp, length); + (seqs_begin, seqs_end, + target, *(seqs_begin->second), length, comp); } // public interface @@ -1861,8 +1887,8 @@ RandomAccessIteratorOut multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length - , __gnu_parallel::exact_tag) + , _DifferenceTp length, Comparator comp + , __gnu_parallel::exact_tag tag) { typedef _DifferenceTp difference_type; _GLIBCXX_CALL(seqs_end - seqs_begin) @@ -1883,17 +1909,16 @@ multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin return parallel_multiway_merge </* stable = */ false, /* sentinels = */ true>( seqs_begin, seqs_end, - target, comp, - multiway_merge_exact_splitting - </* stable = */ false, - typename std::iterator_traits<RandomAccessIteratorPairIterator> - ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); + target, + multiway_merge_exact_splitting</* stable = */ false, + typename std::iterator_traits<RandomAccessIteratorPairIterator> + ::value_type*, Comparator, _DifferenceTp>, + static_cast<difference_type>(length), comp, tag.get_num_threads()); else return sequential_multiway_merge </* stable = */ false, /* sentinels = */ true>( seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); + target, *(seqs_begin->second), length, comp); } // public interface @@ -1903,10 +1928,11 @@ template< , typename _DifferenceTp , typename Comparator> RandomAccessIteratorOut -stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin +multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length) + , _DifferenceTp length, Comparator comp + , sampling_tag tag) { typedef _DifferenceTp difference_type; _GLIBCXX_CALL(seqs_end - seqs_begin) @@ -1925,21 +1951,54 @@ stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin && ((sequence_index_t)length >= __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) return parallel_multiway_merge - </* stable = */ true, /* sentinels = */ true>( - seqs_begin, seqs_end, - target, comp, - multiway_merge_sampling_splitting - </* stable = */ true, - typename std::iterator_traits<RandomAccessIteratorPairIterator> - ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); + </* stable = */ false, /* sentinels = */ true> + (seqs_begin, seqs_end, target, + multiway_merge_sampling_splitting</* stable = */ false, + typename std::iterator_traits<RandomAccessIteratorPairIterator> + ::value_type*, Comparator, _DifferenceTp>, + static_cast<difference_type>(length), comp, tag.get_num_threads()); else return sequential_multiway_merge - </* stable = */ true, /* sentinels = */ true>( + </* stable = */false, /* sentinels = */ true>( seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); + target, *(seqs_begin->second), length, comp); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , parallel_tag tag = parallel_tag(0)) +{ + return multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , default_parallel_tag tag) +{ + return multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); } +// stable_multiway_merge_sentinels // public interface template< typename RandomAccessIteratorPairIterator @@ -1950,7 +2009,7 @@ RandomAccessIteratorOut stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length + , _DifferenceTp length, Comparator comp , __gnu_parallel::sequential_tag) { typedef _DifferenceTp difference_type; @@ -1963,7 +2022,7 @@ stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin // Execute multiway merge *sequentially*. return sequential_multiway_merge </* stable = */ true, /* sentinels = */ true> - (seqs_begin, seqs_end, target, *(seqs_begin->second), comp, length); + (seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp); } // public interface @@ -1976,8 +2035,8 @@ RandomAccessIteratorOut stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin , RandomAccessIteratorPairIterator seqs_end , RandomAccessIteratorOut target - , Comparator comp, _DifferenceTp length - , __gnu_parallel::exact_tag) + , _DifferenceTp length, Comparator comp + , __gnu_parallel::exact_tag tag) { typedef _DifferenceTp difference_type; _GLIBCXX_CALL(seqs_end - seqs_begin) @@ -1998,17 +2057,93 @@ stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin return parallel_multiway_merge </* stable = */ true, /* sentinels = */ true>( seqs_begin, seqs_end, - target, comp, - multiway_merge_exact_splitting - </* stable = */ true, - typename std::iterator_traits<RandomAccessIteratorPairIterator> - ::value_type*, Comparator, _DifferenceTp>, - static_cast<difference_type>(length)); + target, + multiway_merge_exact_splitting</* stable = */ true, + typename std::iterator_traits<RandomAccessIteratorPairIterator> + ::value_type*, Comparator, _DifferenceTp>, + static_cast<difference_type>(length), comp, tag.get_num_threads()); else return sequential_multiway_merge + </* stable = */ true, /* sentinels = */ true>( + seqs_begin, seqs_end, target, *(seqs_begin->second), length, comp); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , sampling_tag tag) +{ + typedef _DifferenceTp difference_type; + _GLIBCXX_CALL(seqs_end - seqs_begin) + + // catch special case: no sequences + if (seqs_begin == seqs_end) + return target; + + // Execute merge; maybe parallel, depending on the number of merged + // elements and the number of sequences and global thresholds in + // Settings. + if ((seqs_end - seqs_begin > 1) && + _GLIBCXX_PARALLEL_CONDITION( + ((seqs_end - seqs_begin) >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_k) + && ((sequence_index_t)length >= + __gnu_parallel::_Settings::get().multiway_merge_minimal_n))) + return parallel_multiway_merge </* stable = */ true, /* sentinels = */ true>( seqs_begin, seqs_end, - target, *(seqs_begin->second), comp, length); + target, + multiway_merge_sampling_splitting</* stable = */ true, + typename std::iterator_traits<RandomAccessIteratorPairIterator> + ::value_type*, Comparator, _DifferenceTp>, + static_cast<difference_type>(length), comp, tag.get_num_threads()); + else + return sequential_multiway_merge + </* stable = */ true, /* sentinels = */ true>( + seqs_begin, seqs_end, + target, *(seqs_begin->second), length, comp); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , parallel_tag tag = parallel_tag(0)) +{ + return stable_multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); +} + +// public interface +template< + typename RandomAccessIteratorPairIterator + , typename RandomAccessIteratorOut + , typename _DifferenceTp + , typename Comparator> +RandomAccessIteratorOut +stable_multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin + , RandomAccessIteratorPairIterator seqs_end + , RandomAccessIteratorOut target + , _DifferenceTp length, Comparator comp + , default_parallel_tag tag) +{ + return stable_multiway_merge_sentinels(seqs_begin, seqs_end, target, length, comp, + exact_tag(tag.get_num_threads())); } }; // namespace __gnu_parallel diff --git a/libstdc++-v3/include/parallel/multiway_mergesort.h b/libstdc++-v3/include/parallel/multiway_mergesort.h index 3791a144d53a088895204dd4e20494a3a775b729..9d9733ad05f5f7c3c8bc41492ab5575f5cdadd3b 100644 --- a/libstdc++-v3/include/parallel/multiway_mergesort.h +++ b/libstdc++-v3/include/parallel/multiway_mergesort.h @@ -289,8 +289,8 @@ template<typename SeqRandomAccessIterator, typename RandomAccessIterator, Comparator& comp, DiffType length_am) const { - stable_multiway_merge(seqs_begin, seqs_end, target, comp, - length_am, sequential_tag()); + stable_multiway_merge(seqs_begin, seqs_end, target, length_am, comp, + sequential_tag()); } }; @@ -306,8 +306,8 @@ template<typename SeqRandomAccessIterator, typename RandomAccessIterator, Comparator& comp, DiffType length_am) const { - multiway_merge(seqs_begin, seqs_end, target, comp, - length_am, sequential_tag()); + multiway_merge(seqs_begin, seqs_end, target, length_am, comp, + sequential_tag()); } }; diff --git a/libstdc++-v3/include/parallel/tags.h b/libstdc++-v3/include/parallel/tags.h index cf937af49525c6258355a3b7fe92a278a3293153..0ca0994e3abce13fdfa30e0daaa6e029bad318a5 100644 --- a/libstdc++-v3/include/parallel/tags.h +++ b/libstdc++-v3/include/parallel/tags.h @@ -47,9 +47,6 @@ namespace __gnu_parallel /** @brief Forces sequential execution at compile time. */ struct sequential_tag { }; - /** @brief Forces exact splitting in multiway merge at compile time. */ - struct exact_tag { }; - /** @brief Recommends parallel execution at compile time, * optionally using a user-specified number of threads. */ struct parallel_tag @@ -119,6 +116,25 @@ namespace __gnu_parallel struct find_tag { }; + /** @brief Forces parallel merging + * with exact splitting, at compile time. */ + struct exact_tag : public parallel_tag + { + exact_tag() { } + exact_tag(thread_index_t num_threads) + : parallel_tag(num_threads) { } + }; + + /** @brief Forces parallel merging + * with exact splitting, at compile time. */ + struct sampling_tag : public parallel_tag + { + sampling_tag() { } + sampling_tag(thread_index_t num_threads) + : parallel_tag(num_threads) { } + }; + + /** @brief Forces parallel sorting using multiway mergesort * at compile time. */ struct multiway_mergesort_tag : public parallel_tag