parallel_mode.xml: Documented the new choices, factoring out common tags.

2008-05-16  Johannes Singler  <singler@ira.uka.de>

         * doc/xml/manual/parallel_mode.xml:
         Documented the new choices, factoring out common tags.
         * include/parallel/multiway_merge.h:
         Place comparison functor at the end, to comply with
         established convention.
         (parallel_multiway_merge) Pass number of threads explicitly.
         Introduce new compile-time variants, make exact splitting the
         default.
         * include/parallel/tags.h:
         Extend exact_tag, introduce sampling_tag.
         * include/parallel/merge.h:
         (parallel_merge_advance) Adapt to changed interface.
         * include/parallel/multiway_mergesort.h: Likewise.

From-SVN: r135411
This commit is contained in:
Johannes Singler 2008-05-16 07:10:26 +00:00
parent fa9290d3b9
commit 36fc59580b
5 changed files with 435 additions and 272 deletions

View File

@ -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>

View File

@ -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;
}

View File

@ -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,50 @@ 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)
// 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,
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 = */ false>(
seqs_begin, seqs_end, 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
, __gnu_parallel::sampling_tag tag)
{
typedef _DifferenceTp difference_type;
_GLIBCXX_CALL(seqs_end - seqs_begin)
@ -1581,16 +1578,16 @@ multiway_merge(RandomAccessIteratorPairIterator seqs_begin
return parallel_multiway_merge
</* stable = */ false, /* sentinels = */ false>(
seqs_begin, seqs_end,
target, comp,
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);
target, *(seqs_begin->second), length, comp);
}
// public interface
@ -1600,42 +1597,34 @@ 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
, parallel_tag tag = parallel_tag(0))
{
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, comp,
multiway_merge_sampling_splitting</* stable = */ true,
typename std::iterator_traits<RandomAccessIteratorPairIterator>
::value_type*, Comparator, _DifferenceTp>,
static_cast<difference_type>(length));
else
return sequential_multiway_merge
</* stable = */ true, /* sentinels = */ false>(
seqs_begin, seqs_end,
target, *(seqs_begin->second), comp, length);
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,7 +1860,79 @@ 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;
_GLIBCXX_CALL(seqs_end - seqs_begin)
// catch special case: no sequences
if (seqs_begin == seqs_end)
return target;
// Execute multiway merge *sequentially*.
return sequential_multiway_merge
</* stable = */ false, /* sentinels = */ true>
(seqs_begin, seqs_end,
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
, __gnu_parallel::exact_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 = */ false, /* sentinels = */ true>(
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), comp, tag.get_num_threads());
else
return sequential_multiway_merge
</* stable = */ false, /* sentinels = */ true>(
seqs_begin, seqs_end,
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
, sampling_tag tag)
{
typedef _DifferenceTp difference_type;
_GLIBCXX_CALL(seqs_end - seqs_begin)
@ -1812,43 +1952,16 @@ multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
__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));
(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 = */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
, __gnu_parallel::sequential_tag)
{
typedef _DifferenceTp difference_type;
_GLIBCXX_CALL(seqs_end - seqs_begin)
// catch special case: no sequences
if (seqs_begin == seqs_end)
return target;
// Execute multiway merge *sequentially*.
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
@ -1861,41 +1974,31 @@ RandomAccessIteratorOut
multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin
, RandomAccessIteratorPairIterator seqs_end
, RandomAccessIteratorOut target
, Comparator comp, _DifferenceTp length
, __gnu_parallel::exact_tag)
, _DifferenceTp length, Comparator comp
, parallel_tag tag = parallel_tag(0))
{
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_exact_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);
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
@ -1906,51 +2009,7 @@ RandomAccessIteratorOut
stable_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 = */ 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));
else
return sequential_multiway_merge
</* stable = */ true, /* sentinels = */ true>(
seqs_begin, seqs_end,
target, *(seqs_begin->second), comp, length);
}
// public interface
template<
typename RandomAccessIteratorPairIterator
, typename RandomAccessIteratorOut
, typename _DifferenceTp
, typename Comparator>
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,
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), comp, length);
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

View File

@ -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());
}
};

View File

@ -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