__gnu_parallel(3cxx)
โจ NAME โจ
okay bestie, welcome to the __gnu_parallel(3cxx) page ๐
โ __gnu_parallel is literally the GNU parallel code for public use. that's the whole name vibe, no cap.
๐ธ SYNOPSIS ๐ธ
this page is the master list of the public parallel machinery: a whole pile of classes and structs, some typedefs, and the enums. it's giving legendary template energy, so stay with me โจ
๐ Classes
__accumulate_binop_reductโ general reduction using a binary operator. lowkey the reduce bestie.__accumulate_selectorโ thestd::accumulate()selector. slay.__adjacent_difference_selectorโ selector that gives back the difference between two adjacent__elements.__adjacent_find_selectorโ tests a predicate on two adjacent elements.__binder1stโ likestd::binder1st, but it hands the argument types over explicitly.__binder2ndโ same deal asstd::binder2nd, with the argument types given explicitly.__count_if_selectorโ thestd::count_if ()selector.__count_selectorโ thestd::count()selector.__fill_selectorโ thestd::fill()selector.__find_first_of_selectorโ tests a predicate on several elements.__find_if_selectorโ tests a predicate on a single element, and it's used forstd::find()andstd::find_if ().__for_each_selectorโ thestd::for_each()selector.__generate_selectorโ thestd::generate()selector.__generic_find_selectorโ base class of all__gnu_parallel::__find_templateselectors.__generic_for_each_selectorโ generic__selectorfor embarrassingly parallel functions.__identity_selectorโ selector that just returns the iterator you passed in. no thoughts, just vibes.__inner_product_selectorโ thestd::inner_product()selector.__max_element_reductโ reduction for finding the maximum element, using a comparator.__min_element_reductโ reduction for finding the maximum element, using a comparator. yes, the page says maximum here too โ I'm just reporting the facts ๐ซถ__mismatch_selectorโ tests an inverted predicate on a single element.__multiway_merge_3_variant_sentinel_switchโ switch for 3-way merging with__sentinelsturned off.__multiway_merge_3_variant_sentinel_switch< true, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare >โ switch for 3-way merging with__sentinelsturned on.__multiway_merge_4_variant_sentinel_switchโ switch for 4-way merging with__sentinelsturned off.__multiway_merge_4_variant_sentinel_switch< true, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare >โ switch for 4-way merging with__sentinelsturned on.__multiway_merge_k_variant_sentinel_switchโ switch for k-way merging with__sentinelsturned on.__multiway_merge_k_variant_sentinel_switch< false, __stable, _RAIterIterator, _RAIter3, _DifferenceTp, _Compare >โ switch for k-way merging with__sentinelsturned off.__replace_if_selectorโ thestd::replace()selector.__replace_selectorโ thestd::replace()selector.__transform1_selectorโstd::transform()__selector, one input sequence variant.__transform2_selectorโstd::transform()__selector, two input sequences variant.__unary_negateโ likestd::unary_negate, but with the argument types given explicitly._DRandomShufflingGlobalDataโ data known to every thread participating in__gnu_parallel::__parallel_random_shuffle()._DRSSorterPUโ local data for a thread participating in__gnu_parallel::__parallel_random_shuffle()._DummyReductโ reduction function doing absolutely nothing. iconic._EqualFromLessโ builds an equality predicate from a strict weak ordering predicate._EqualToโ likestd::equal_to, but it allows two different types._GuardedIteratorโ_Iteratorwrapper supporting an implicit supremum at the end of the sequence, dominating all comparisons._IteratorPairโ a pair of iterators. the usual iterator operations are applied to both child iterators._IteratorTripleโ a triple of iterators. the usual iterator operations are applied to all three child iterators._Jobโ one__jobfor a certain thread._Lessโ likestd::less, but it allows two different types._Lexicographicโ compares a pair of types lexicographically, ascending._LexicographicReverseโ compares a pair of types lexicographically, descending._LoserTreeโ stable_LoserTreevariant._LoserTree< false, _Tp, _Compare >โ unstable_LoserTreevariant._LoserTreeBaseโ guarded loser/tournament tree._LoserTreePointerโ stable_LoserTreeimplementation._LoserTreePointer< false, _Tp, _Compare >โ unstable_LoserTreeimplementation._LoserTreePointerBaseโ base class of_Loser Treeimplementation using pointers._LoserTreePointerUnguardedโ stable unguarded_LoserTreevariant storing pointers._LoserTreePointerUnguarded< false, _Tp, _Compare >โ unstable unguarded_LoserTreevariant storing pointers._LoserTreePointerUnguardedBaseโ unguarded loser tree, keeping only pointers to the elements in the tree structure._LoserTreeTraitsโ traits for determining whether the loser tree should use pointers or copies._LoserTreeUnguardedโ stable implementation of unguarded_LoserTree._LoserTreeUnguarded< false, _Tp, _Compare >โ non-stable implementation of unguarded_LoserTree._LoserTreeUnguardedBaseโ base class for unguarded_LoserTreeimplementation._Multipliesโ likestd::multiplies, but it allows two different types._Nothingโ functor doing nothing._Pieceโ subsequence description._Plusโ likestd::plus, but it allows two different types._PMWMSSortingDataโ data accessed by all threads._PseudoSequenceโ sequence that conceptually consists of multiple copies of the same element. the copies are not stored explicitly, of course._PseudoSequenceIteratorโ_Iteratorassociated with__gnu_parallel::_PseudoSequence. it features the usual random-access iterator functionality._QSBThreadLocalโ information local to one thread in the parallel quicksort run._RandomNumberโ random number generator based on the Mersenne twister._RestrictedBoundedConcurrentQueueโ double-ended queue of bounded size, allowing lock-free atomic access.push_front()andpop_front()must not be called concurrently to each other, whilepop_back()can be called concurrently at all times.empty(),size(), andtop()are intentionally not provided โ calling them would not make sense in a concurrent setting. periodt._SamplingSorterโ stable sorting functor._SamplingSorter< false, _RAIter, _StrictWeakOrdering >โ non-__stablesorting functor._Settingsโ class_Settingsrun-time settings for the parallel mode, including all tunable parameters._SplitConsistentlyโ split consistently._SplitConsistently< false, _RAIter, _Compare, _SortingPlacesIterator >โ split by sampling._SplitConsistently< true, _RAIter, _Compare, _SortingPlacesIterator >โ split by exact splitting.balanced_quicksort_tagโ forces parallel sorting using balanced quicksort at compile time.balanced_tagโ recommends parallel execution using dynamic load-balancing at compile time.constant_size_blocks_tagโ selects the constant block size variant forstd::find().default_parallel_tagโ recommends parallel execution using the default parallel algorithm.equal_split_tagโ selects the equal splitting variant forstd::find().exact_tagโ forces parallel merging with exact splitting, at compile time.find_tagโ base class for forstd::find()variants.growing_blocks_tagโ selects the growing block size variant forstd::find().multiway_mergesort_exact_tagโ forces parallel sorting using multiway mergesort with exact splitting at compile time.multiway_mergesort_sampling_tagโ forces parallel sorting using multiway mergesort with splitting by sampling at compile time.multiway_mergesort_tagโ forces parallel sorting using multiway mergesort at compile time.omp_loop_static_tagโ recommends parallel execution using OpenMP static load-balancing at compile time.omp_loop_tagโ recommends parallel execution using OpenMP dynamic load-balancing at compile time.parallel_tagโ recommends parallel execution at compile time, optionally using a user-specified number of threads.quicksort_tagโ forces parallel sorting using unbalanced quicksort at compile time.sampling_tagโ forces parallel merging with exact splitting, at compile time.sequential_tagโ forces sequential execution at compile time.unbalanced_tagโ recommends parallel execution using static load-balancing at compile time.
โจ Typedefs
_BinIndexโtypedef unsigned short. type to hold the index of a bin._CASableโtypedef int64_t. longest compare-and-swappable integer type on this platform._SequenceIndexโtypedef uint64_t. unsigned integer to index__elements. the total number of elements for each algorithm must fit into this type._ThreadIndexโtypedef uint16_t. unsigned integer to index a thread number. the maximum thread number (for each processor) must fit into this type.
๐ Enumerations
_AlgorithmStrategy { heuristic, force_sequential, force_parallel }โ strategies for run-time algorithm selection._FindAlgorithm { GROWING_BLOCKS, CONSTANT_SIZE_BLOCKS, EQUAL_SPLIT }โ find algorithms._MultiwayMergeAlgorithm { LOSER_TREE }โ merging algorithms._Parallelism { sequential, parallel_unbalanced, parallel_balanced, parallel_omp_loop, parallel_omp_loop_static, parallel_taskqueue }โ run-time equivalents for the compile-time tags._PartialSumAlgorithm { RECURSIVE, LINEAR }โ partial sum algorithms: recursive, linear._SortAlgorithm { MWMS, QS, QS_BALANCED }โ sorting algorithms._SplittingAlgorithm { SAMPLING, EXACT }โ sorting/merging algorithms: sampling,__exact.
โจ Functions โจ
Okay bestie, buckle up ๐ โ this is the big function list, like the entire backstage crew of the library, and every single signature is coming with us. Some of them have a lil blurb attached, some are just the signature and the vibes, and honestly? We respect both.
template<typename _Tp > _Tp __add_omp (volatile _Tp *__ptr, _Tp __addend)โ no description on this one, just the signature doing its thing ๐ซถtemplate<typename _RAIter , typename _DifferenceTp > void __calc_borders (_RAIter __elements, _DifferenceTp __length, _DifferenceTp *__off)โ precalculates the__advancesfor the Knuth-Morris-Pratt algorithm. Literally the prep work so KMP can slay later โจtemplate<typename _Tp > bool __cas_omp (volatile _Tp *__ptr, _Tp __comparand, _Tp __replacement)โ signature only, no extra notes, we move ๐template<typename _Tp > bool __compare_and_swap (volatile _Tp *__ptr, _Tp __comparand, _Tp __replacement)โ compare-and-swap. That's the entire note, short and iconic ๐template<typename _IIter , typename _OutputIterator > _OutputIterator __copy_tail (std::pair< _IIter, _IIter > __b, std::pair< _IIter, _IIter > __e, _OutputIterator __r)โ no blurb here either, just take the signature as given ๐void __decode2 (_CASable __x, int &__a, int &__b)โ decodes two integers out of onegnu_parallel::_CASable. Two-for-one situation, lowkey efficient ๐ฆtemplate<typename _RAIter , typename _DifferenceTp > void __determine_samples (_PMWMSSortingData< _RAIter > *__sd, _DifferenceTp __num_samples)โ selects_M_samplesfrom a sequence. Note the underscore, bestie, it's_M_samples, don't come for me ๐_CASable __encode2 (int __a, int __b)โ encodes two integers into onegnu_parallel::_CASable. The exact reverse of the girl above, we love a matching set ๐ธtemplate<typename _DifferenceType , typename _OutputIterator > _OutputIterator __equally_split (_DifferenceType __n, _ThreadIndex __num_threads, _OutputIterator __s)โ a function to split a sequence into parts of almost equal size. Almost, okay, nobody's perfect ๐template<typename _DifferenceType > _DifferenceType __equally_split_point (_DifferenceType __n, _ThreadIndex __num_threads, _ThreadIndex __thread_no)โ also a function to split a sequence into parts of almost equal size, except this one hands you the point โจtemplate<typename _Tp > _Tp __fetch_and_add (volatile _Tp *__ptr, _Tp __addend)โ adds a value to a variable, atomically. No race conditions invited to this party ๐ฅtemplate<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename _Selector > std::pair< _RAIter1, _RAIter2 > __find_template (_RAIter1 __begin1, _RAIter1 __end1, _RAIter2 __begin2, _Pred __pred, _Selector __selector)โ parallelstd::find, switching between different algorithms depending on what you hand it ๐งtemplate<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename _Selector > std::pair< _RAIter1, _RAIter2 > __find_template (_RAIter1 __begin1, _RAIter1 __end1, _RAIter2 __begin2, _Pred __pred, _Selector __selector, constant_size_blocks_tag)โ parallelstd::find, the constant block size variant ๐template<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename _Selector > std::pair< _RAIter1, _RAIter2 > __find_template (_RAIter1 __begin1, _RAIter1 __end1, _RAIter2 __begin2, _Pred __pred, _Selector __selector, equal_split_tag)โ parallelstd::find, the equal splitting variant ๐template<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename _Selector > std::pair< _RAIter1, _RAIter2 > __find_template (_RAIter1 __begin1, _RAIter1 __end1, _RAIter2 __begin2, _Pred __pred, _Selector __selector, growing_blocks_tag)โ parallelstd::find, the growing block size variant. Four flavours, all valid ๐template<typename _IIter , typename _UserOp , typename _Functionality , typename _Red , typename _Result > _UserOp __for_each_template_random_access (_IIter __begin, _IIter __end, _UserOp __user_op, _Functionality &__functionality, _Red __reduction, _Result __reduction_start, _Result &__output, typename std::iterator_traits< _IIter >::difference_type __bound, _Parallelism __parallelism_tag)โ picks the algorithm you want by checking out__parallelism_tag๐template<typename _RAIter , typename _Op , typename _Fu , typename _Red , typename _Result > _Op __for_each_template_random_access_ed (_RAIter __begin, _RAIter __end, _Op __o, _Fu &__f, _Red __r, _Result __base, _Result &__output, typename std::iterator_traits< _RAIter >::difference_type __bound)โ the embarrassingly parallel algorithm for random access iterators, using hand-crafted parallelization by equal splitting the work. Hand-crafted, bestie, artisanal parallelization ๐template<typename _RAIter , typename _Op , typename _Fu , typename _Red , typename _Result > _Op __for_each_template_random_access_omp_loop (_RAIter __begin, _RAIter __end, _Op __o, _Fu &__f, _Red __r, _Result __base, _Result &__output, typename std::iterator_traits< _RAIter >::difference_type __bound)โ the embarrassingly parallel algorithm for random access iterators, using an OpenMPforloop โจtemplate<typename _RAIter , typename _Op , typename _Fu , typename _Red , typename _Result > _Op __for_each_template_random_access_omp_loop_static (_RAIter __begin, _RAIter __end, _Op __o, _Fu &__f, _Red __r, _Result __base, _Result &__output, typename std::iterator_traits< _RAIter >::difference_type __bound)โ same embarrassingly parallel algorithm for random access iterators, but with an OpenMPforloop using static scheduling ๐ฆtemplate<typename _RAIter , typename _Op , typename _Fu , typename _Red , typename _Result > _Op __for_each_template_random_access_workstealing (_RAIter __begin, _RAIter __end, _Op __op, _Fu &__f, _Red __r, _Result __base, _Result &__output, typename std::iterator_traits< _RAIter >::difference_type __bound)โ the work stealing algorithm for random access iterators. Note it's__ophere, not__oโ little details, we notice them ๐_ThreadIndex __get_max_threads ()โ signature only, no blurb, mysterious main character energy ๐bool __is_parallel (const _Parallelism __p)โ also just the signature. Giving nothing, serving everything ๐ธtemplate<typename _IIter , typename _Compare > bool __is_sorted (_IIter __begin, _IIter __end, _Compare __comp)โ checks whether[__begin, __end)is sorted according to__comp. The vibe check of sequences โtemplate<typename _RAIter , typename _Compare > _RAIter __median_of_three_iterators (_RAIter __a, _RAIter __b, _RAIter __c, _Compare __comp)โ computes the median of three referenced elements, according to__comp๐template<typename _RAIter1 , typename _RAIter2 , typename _OutputIterator , typename _DifferenceTp , typename _Compare > _OutputIterator __merge_advance (_RAIter1 &__begin1, _RAIter1 __end1, _RAIter2 &__begin2, _RAIter2 __end2, _OutputIterator __target, _DifferenceTp __max_length, _Compare __comp)โ a merge routine that can only merge the__max_lengthsmallest elements ๐ฅtemplate<typename _RAIter1 , typename _RAIter2 , typename _OutputIterator , typename _DifferenceTp , typename _Compare > _OutputIterator __merge_advance_movc (_RAIter1 &__begin1, _RAIter1 __end1, _RAIter2 &__begin2, _RAIter2 __end2, _OutputIterator __target, _DifferenceTp __max_length, _Compare __comp)โ another merge routine that can only merge the__max_lengthsmallest elements ๐งtemplate<typename _RAIter1 , typename _RAIter2 , typename _OutputIterator , typename _DifferenceTp , typename _Compare > _OutputIterator __merge_advance_usual (_RAIter1 &__begin1, _RAIter1 __end1, _RAIter2 &__begin2, _RAIter2 __end2, _OutputIterator __target, _DifferenceTp __max_length, _Compare __comp)โ and a third merge routine that can only merge the__max_lengthsmallest elements. Three of them, all saying the same line, iconic behaviour honestly ๐template<typename _RAIter1 , typename _RAIter3 , typename _Compare > _RAIter3 __parallel_merge_advance (_RAIter1 &__begin1, _RAIter1 __end1, _RAIter1 &__begin2, _RAIter1 __end2, _RAIter3 __target, typename std::iterator_traits< _RAIter1 >::difference_type __max_length, _Compare __comp)โ a parallel merge routine that can only merge the__max_lengthsmallest elements ๐template<typename _RAIter1 , typename _RAIter2 , typename _RAIter3 , typename _Compare > _RAIter3 __parallel_merge_advance (_RAIter1 &__begin1, _RAIter1 __end1, _RAIter2 &__begin2, _RAIter2 __end2, _RAIter3 __target, typename std::iterator_traits< _RAIter1 >::difference_type __max_length, _Compare __comp)โ the merge routine that falls back to sequential in case the iterators of the two input sequences are of different type. Plan B, but make it cute ๐template<typename _RAIter , typename _Compare > void __parallel_nth_element (_RAIter __begin, _RAIter __nth, _RAIter __end, _Compare __comp)โ parallel implementation ofstd::nth_element()โจtemplate<typename _RAIter , typename _Compare > void __parallel_partial_sort (_RAIter __begin, _RAIter __middle, _RAIter __end, _Compare __comp)โ parallel implementation ofstd::partial_sort()๐template<typename _IIter , typename _OutputIterator , typename _BinaryOperation > _OutputIterator __parallel_partial_sum (_IIter __begin, _IIter __end, _OutputIterator __result, _BinaryOperation __bin_op)โ parallel partial sum, front-__end. Yes the original says front-__end, we're keeping it ๐ซถtemplate<typename _IIter , typename _OutputIterator , typename _BinaryOperation > _OutputIterator __parallel_partial_sum_basecase (_IIter __begin, _IIter __end, _OutputIterator __result, _BinaryOperation __bin_op, typename std::iterator_traits< _IIter >::value_type __value)โ the base case prefix sum routine, the lil foundation of the whole thing ๐template<typename _IIter , typename _OutputIterator , typename _BinaryOperation > _OutputIterator __parallel_partial_sum_linear (_IIter __begin, _IIter __end, _OutputIterator __result, _BinaryOperation __bin_op, typename std::iterator_traits< _IIter >::difference_type __n)โ the parallel partial sum implementation: two-phase approach, and no recursion ๐ธtemplate<typename _RAIter , typename _Predicate > std::iterator_traits< _RAIter >::difference_type __parallel_partition (_RAIter __begin, _RAIter __end, _Predicate __pred, _ThreadIndex __num_threads)โ parallel implementation ofstd::partition๐ฅtemplate<typename _RAIter , typename _RandomNumberGenerator > void __parallel_random_shuffle (_RAIter __begin, _RAIter __end, _RandomNumberGenerator __rng=_RandomNumber())โ parallel random public call. Default arg is right there,__rng=_RandomNumber(), don't miss it ๐template<typename _RAIter , typename _RandomNumberGenerator > void __parallel_random_shuffle_drs (_RAIter __begin, _RAIter __end, typename std::iterator_traits< _RAIter >::difference_type __n, _ThreadIndex __num_threads, _RandomNumberGenerator &__rng)โ the main parallel random shuffle step, the big one ๐งtemplate<typename _RAIter , typename _RandomNumberGenerator > void __parallel_random_shuffle_drs_pu (_DRSSorterPU< _RAIter, _RandomNumberGenerator > *__pus)โ the random shuffle code that each thread actually executes. Teamwork, but make it shuffling ๐template<typename _IIter , typename _OutputIterator , typename _Compare > _OutputIterator __parallel_set_difference (_IIter __begin1, _IIter __end1, _IIter __begin2, _IIter __end2, _OutputIterator __result, _Compare __comp)โ signature only, no blurb attached, we take it ๐template<typename _IIter , typename _OutputIterator , typename _Compare > _OutputIterator __parallel_set_intersection (_IIter __begin1, _IIter __end1, _IIter __begin2, _IIter __end2, _OutputIterator __result, _Compare __comp)โ same deal, no description, just vibes ๐template<typename _IIter , typename _OutputIterator , typename _Operation > _OutputIterator __parallel_set_operation (_IIter __begin1, _IIter __end1, _IIter __begin2, _IIter __end2,โ this one's signature trails right off the edge of the page ๐ญ hold that thought, it keeps going in a sec.template<typename _IIter , typename _OutputIterator , typename _Compare > _OutputIterator __parallel_set_symmetric_difference (_IIter __begin1, _IIter __end1, _IIter __begin2, _IIter __end2, _OutputIterator __result, _Compare __comp)โ the symmetric-difference set op, parallel-flavored. The page gives it no blurb, so that's all we've got, bestie โจtemplate<typename _IIter , typename _OutputIterator , typename _Compare > _OutputIterator __parallel_set_union (_IIter __begin1, _IIter __end1, _IIter __begin2, _IIter __end2, _OutputIterator __result, _Compare __comp)โ and the union one, same deal. No description in the source, no cap ๐ซถ
the __parallel_sort glow-up squad ๐
Okay so there's one generic __parallel_sort and then a whole little clique of overloads that each pick a different algorithm for you based on the tag you hand over. It's giving "choose your fighter."
template<bool __stable, typename _RAIter , typename _Compare , typename _Parallelism > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, _Parallelism __parallelism)โ the generic one, takes whatever_Parallelismyou throw at it.template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, balanced_quicksort_tag __parallelism)โ choose balanced quicksort for parallel sorting ๐template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, default_parallel_tag __parallelism)โ choose multiway mergesort with exact splitting, for parallel sorting.template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, multiway_mergesort_exact_tag __parallelism)โ choose multiway mergesort with exact splitting, for parallel sorting (yes, same wording as the default one โ that's genuinely what the page says ๐ซ ).template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, multiway_mergesort_sampling_tag __parallelism)โ choose multiway mergesort with splitting by sampling, for parallel sorting.template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, multiway_mergesort_tag __parallelism)โ choose multiway mergesort, splitting variant decided at run-time, for parallel sorting.template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, parallel_tag __parallelism)โ choose a parallel sorting algorithm. Vague on purpose, iconic behavior.template<bool __stable, typename _RAIter , typename _Compare > void __parallel_sort (_RAIter __begin, _RAIter __end, _Compare __comp, quicksort_tag __parallelism)โ choose quicksort for parallel sorting.
the quicksort internals ๐
These are the machinery behind the quicksort tags โ lowkey the main characters of the sort implementation, highkey not something you call yourself.
template<typename _RAIter , typename _Compare > void __parallel_sort_qs (_RAIter __begin, _RAIter __end, _Compare __comp, _ThreadIndex __num_threads)โ unbalanced quicksort main call.template<typename _RAIter , typename _Compare > void __parallel_sort_qs_conquer (_RAIter __begin, _RAIter __end, _Compare __comp, _ThreadIndex __num_threads)โ unbalanced quicksort conquer step.template<typename _RAIter , typename _Compare > std::iterator_traits< _RAIter >::difference_type __parallel_sort_qs_divide (_RAIter __begin, _RAIter __end, _Compare __comp, typename std::iterator_traits< _RAIter >::difference_type __pivot_rank, typename std::iterator_traits< _RAIter >::difference_type __num_samples, _ThreadIndex __num_threads)โ unbalanced quicksort divide step.template<typename _RAIter , typename _Compare > void __parallel_sort_qsb (_RAIter __begin, _RAIter __end, _Compare __comp, _ThreadIndex __num_threads)โ top-level quicksort routine โจtemplate<typename _RAIter , typename _Compare > void __qsb_conquer (_QSBThreadLocal< _RAIter > **__tls, _RAIter __begin, _RAIter __end, _Compare __comp, _ThreadIndex __iam, _ThreadIndex __num_threads, bool __parent_wait)โ quicksort conquer step (theqsbbranch this time).template<typename _RAIter , typename _Compare > std::iterator_traits< _RAIter >::difference_type __qsb_divide (_RAIter __begin, _RAIter __end, _Compare __comp, _ThreadIndex __num_threads)โ balanced quicksort divide step.template<typename _RAIter , typename _Compare > void __qsb_local_sort_with_helping (_QSBThreadLocal< _RAIter > **__tls, _Compare &__comp, _ThreadIndex __iam, bool __wait)โ quicksort step doing load-balanced local sort. Helping hands fr fr ๐ซถ
tiny math + random helpers ๐
template<typename _RandomNumberGenerator > int __random_number_pow2 (int __logp, _RandomNumberGenerator &__rng)โ generate a random number in[0,2^__logp).template<typename _Size > _Size __rd_log2 (_Size __n)โ calculates the rounded-down logarithm of__nfor base 2.template<typename _Tp > _Tp __round_up_to_pow2 (_Tp __x)โ round up to the next greater power of 2 โญ
search, merge-ish, and shuffle-adjacent ๐
template<typename __RAIter1 , typename __RAIter2 , typename _Pred > __RAIter1 __search_template (__RAIter1 __begin1, __RAIter1 __end1, __RAIter2 __begin2, __RAIter2 __end2, _Pred __pred)โ parallelstd::search.template<bool __stable, bool __sentinels, typename _RAIterIterator , typename _RAIter3 , typename _DifferenceTp , typename _Compare > _RAIter3 __sequential_multiway_merge (_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, const typename std::iterator_traits< typename std::iterator_traits< _RAIterIterator >::value_type::first_type >::value_type &__sentinel, _DifferenceTp __length, _Compare __comp)โ the sequential multi-way merging switch (the one that decides the strategy).template<typename _RAIter , typename _RandomNumberGenerator > void __sequential_random_shuffle (_RAIter __begin, _RAIter __end, _RandomNumberGenerator &__rng)โ sequential, cache-efficient random shuffle. Yes bestie, cache-efficient and random ๐
range-shrinking era ๐ฆ
template<typename _IIter > void __shrink (std::vector< _IIter > &__os_starts, size_t &__count_to_two, size_t &__range_length)โ combines two ranges into one, and thus halves the number of ranges.template<typename _IIter > void __shrink_and_double (std::vector< _IIter > &__os_starts, size_t &__count_to_two, size_t &__range_length, const bool __make_twice)โ shrinks and doubles the ranges. Growth mindset, honestly.
odds and ends ๐
void __yield ()โ yield control to another thread, without waiting for the end of the time slice. Politely stepping aside, no waiting around.template<typename _IIter , typename _FunctorType > size_t list_partition (const _IIter __begin, const _IIter __end, _IIter *__starts, size_t *__lengths, const int __num_parts, _FunctorType &__f, int __oversampling=0)โ splits a sequence given by input iterators into parts of almost equal size. Note the default:__oversampling=0.template<typename _Tp > const _Tp & max (const _Tp &__a, const _Tp &__b)โ equivalent tostd::max.template<typename _Tp > const _Tp & min (const _Tp &__a, const _Tp &__b)โ equivalent tostd::min.template<typename _RanSeqs , typename _RankType , typename _RankIterator , typename _Compare > void multiseq_partition (_RanSeqs __begin_seqs, _RanSeqs __end_seqs, _RankType __rank, _RankIterator __begin_offsets, _Compare __comp=std::less< typename std::iterator_traits< typename std::iterator_traits< _RanSeqs >::value_type::first_type >::value_type >())โ splits several sorted sequences at a certain global__rank, resulting in a splitting point for each sequence. The sequences are passed via a sequence of random-access iterator pairs, and none of the sequences may be empty โ ๏ธ โ that's a hard requirement, not a vibe suggestion. If there are several equal elements across the split, the ones on the__leftside will be chosen from sequences with smaller number.template<typename _Tp , typename _RanSeqs , typename _RankType , typename _Compare > _Tp multiseq_selection (_RanSeqs __begin_seqs, _RanSeqs __end_seqs, _RankType __rank, _RankType &__offset, _Compare __comp=std::less< _Tp >())โ selects the element at a certain global__rankfrom several sorted sequences.
multiway_merge frontends ๐
So multiway_merge is one name with a million tag-based personalities. The page only labels the sequential_tag one; the rest are just overloads sitting there looking pretty:
template<typename _RAIterPairIterator , typename _RAIterOut , typename _DifferenceTp , typename _Compare > _RAIterOut multiway_merge (_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, __gnu_parallel::exact_tag __tag)template<typename _RAIterPairIterator , typename _RAIterOut , typename _DifferenceTp , typename _Compare > _RAIterOut multiway_merge (_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, __gnu_parallel::sampling_tag __tag)template<typename _RAIterPairIterator , typename _RAIterOut , typename _DifferenceTp , typename _Compare > _RAIterOut multiway_merge (_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, __gnu_parallel::sequential_tag)โ multiway merge frontend. That's the whole blurb, and honestly, respect for the brevity ๐template<typename _RAIterPairIterator , typename _RAIterOut , typename _DifferenceTp , typename _Compare > _RAIterOut multiway_merge (_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, default_parallel_tag __tag)template<typename _RAIterPairIterator , typename _RAIterOut , typename _DifferenceTp , typename _Compare > _RAIterOut multiway_merge (_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp __length, _Compare __comp, parallel_tag __tag=parallel_tag(0))
heads up, the source page really does end that last signature with parallel_tag(0)) โ the extra paren is copy-pasted straight from the manpage, iykyk ๐
the variant algorithms โจ
template<template< typename _RAI, typename _Cp > class iterator, typename _RAIterIterator , typename _RAIter3 , typename _DifferenceTp , typename _Compare > _RAIter3 multiway_merge_3_variant (_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp __length, _Compare __comp)โ highly efficient 3-way merging procedure ๐ฅtemplate<template< typename _RAI, typename _Cp > class iterator, typename _RAIterIterator , typename _RAIter3 , typename _DifferenceTp , typename _Compare > _RAIter3 multiway_merge_4_variant (_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp __length, _Compare __comp)โ highly efficient 4-way merging procedure ๐ฅtemplate<bool __stable, typename _RAIterIterator , typename _Compare , typename _DifferenceType > void multiway_merge_exact_splitting (_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,โ and the page justโฆ stops there mid-signature ๐ญ that's literally where this chunk ends, bestie, so we pick it up next part.- that one whose signature got cut off mid-argument (the manpage does that, not me, don't @ me ๐) โ
_DifferenceType __length, _DifferenceType __total_length, _Compare
__comp, std::vector< std::pair< _DifferenceType, _DifferenceType > >
*__pieces)
Exact splitting for parallel multiway-merge routine. okay so it's exact, no vibes-based guessing here ๐
multiway_merge_loser_tree
template<typename _LT , typename _RAIterIterator , typename _RAIter3 ,
typename _DifferenceTp , typename _Compare > _RAIter3
multiway_merge_loser_tree (_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp
__length, _Compare __comp)
Multi-way merging procedure for a high branching factor, guarded case. ๐ก๏ธ
multiway_merge_loser_tree_sentinel
template<typename _UnguardedLoserTree , typename _RAIterIterator ,
typename _RAIter3 , typename _DifferenceTp , typename _Compare >
_RAIter3 multiway_merge_loser_tree_sentinel (_RAIterIterator
__seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, const
typename std::iterator_traits< typename std::iterator_traits<
_RAIterIterator >::value_type::first_type >::value_type &__sentinel,
_DifferenceTp __length, _Compare __comp)
Multi-way merging procedure for a high branching factor, requiring sentinels to exist. sentinels are the little bodyguards fr fr ๐ซถ
multiway_merge_loser_tree_unguarded
template<typename _LT , typename _RAIterIterator , typename _RAIter3 ,
typename _DifferenceTp , typename _Compare > _RAIter3
multiway_merge_loser_tree_unguarded (_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_end, _RAIter3 __target, const typename
std::iterator_traits< typename std::iterator_traits< _RAIterIterator
>::value_type::first_type >::value_type &__sentinel, _DifferenceTp
__length, _Compare __comp)
Multi-way merging procedure for a high branching factor, unguarded case. living dangerously, no guard rails, no cap ๐ญ
multiway_merge_sampling_splitting
template<bool __stable, typename _RAIterIterator , typename _Compare ,
typename _DifferenceType > void multiway_merge_sampling_splitting
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end,
_DifferenceType __length, _DifferenceType __total_length, _Compare
__comp, std::vector< std::pair< _DifferenceType, _DifferenceType > >
*__pieces)
Sampling based splitting for parallel multiway-merge routine. it's giving "just take a lil sample, bestie" โจ
multiway_merge_sentinels(the__gnu_parallel::exact_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, __gnu_parallel::exact_tag __tag)
multiway_merge_sentinels(the__gnu_parallel::sequential_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, __gnu_parallel::sequential_tag)
Multiway Merge Frontend. this is the main character entry point ๐
multiway_merge_sentinels(thedefault_parallel_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, default_parallel_tag __tag)
multiway_merge_sentinels(theparallel_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, parallel_tag __tag=parallel_tag(0))
multiway_merge_sentinels(thesampling_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, sampling_tag __tag)
yes bestie, that's five overloads of the same name โ it's the tag-dispatch buffet, pick your flavor ๐
parallel_multiway_merge
template<bool __stable, bool __sentinels, typename _RAIterIterator ,
typename _RAIter3 , typename _DifferenceTp , typename _Splitter ,
typename _Compare > _RAIter3 parallel_multiway_merge
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3
__target, _Splitter __splitter, _DifferenceTp __length, _Compare
__comp, _ThreadIndex __num_threads)
Parallel multi-way merge routine. the whole point of the function tbh ๐ฅ
parallel_sort_mwms
template<bool __stable, bool __exact, typename _RAIter , typename
_Compare > void parallel_sort_mwms (_RAIter __begin, _RAIter __end,
_Compare __comp, _ThreadIndex __num_threads)
PMWMS main call. that acronym will live in my head rent free ๐ง โจ
parallel_sort_mwms_pu
template<bool __stable, bool __exact, typename _RAIter , typename
_Compare > void parallel_sort_mwms_pu (_PMWMSSortingData< _RAIter >
*__sd, _Compare &__comp)
PMWMS code executed by each thread. every thread gets a lil job, teamwork makes the dream work ๐ซถ
stable_multiway_merge(the__gnu_parallel::exact_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut stable_multiway_merge
(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end,
_RAIterOut __target, _DifferenceTp __length, _Compare __comp,
__gnu_parallel::exact_tag __tag)
stable_multiway_merge(the__gnu_parallel::sequential_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut stable_multiway_merge
(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end,
_RAIterOut __target, _DifferenceTp __length, _Compare __comp,
__gnu_parallel::sequential_tag)
stable_multiway_merge(thedefault_parallel_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut stable_multiway_merge
(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end,
_RAIterOut __target, _DifferenceTp __length, _Compare __comp,
default_parallel_tag __tag)
stable_multiway_merge(theparallel_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut stable_multiway_merge
(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end,
_RAIterOut __target, _DifferenceTp __length, _Compare __comp,
parallel_tag __tag=parallel_tag(0))
stable_multiway_merge(thesampling_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut stable_multiway_merge
(_RAIterPairIterator __seqs_begin, _RAIterPairIterator __seqs_end,
_RAIterOut __target, _DifferenceTp __length, _Compare __comp,
sampling_tag __tag)
stable_multiway_merge_sentinels(the__gnu_parallel::exact_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
stable_multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, __gnu_parallel::exact_tag __tag)
stable_multiway_merge_sentinels(the__gnu_parallel::sequential_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
stable_multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, __gnu_parallel::sequential_tag)
stable_multiway_merge_sentinels(thedefault_parallel_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
stable_multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, default_parallel_tag __tag)
stable_multiway_merge_sentinels(theparallel_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
stable_multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, parallel_tag __tag=parallel_tag(0))
stable_multiway_merge_sentinels(thesampling_tagone)
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
stable_multiway_merge_sentinels (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, sampling_tag __tag)
๐งฎ Variables
static const int _CASable_bitsโ Number of bits of_CASable. bestie, it's literally just counting bits ๐static const _CASable _CASable_maskโ_CASablewith the right half of bits set to1. mask era ๐ญ
๐ธ Detailed Description
GNU parallel code for public use. that's it, that's the whole vibe check โ this is the public-facing surface of the GNU parallel machinery โจ
๐ Typedef Documentation
typedef unsigned short __gnu_parallel::_BinIndex
Type to hold the index of a bin. Since many variables of this type are allocated, it should be chosen as small as possible. tiny type, big responsibility โ it's giving efficiency queen ๐
typedef int64_t __gnu_parallel::_CASable
Longest compare-and-swappable integer type on this platform. as long as it can legally get on this machine, no cap ๐ซถ
typedef uint64_t __gnu_parallel::_SequenceIndex
Unsigned integer to index __elements. The total number of elements for each algorithm must fit into this type. so like, mind the capacity, bestie ๐ญ
typedef uint16_t __gnu_parallel::_ThreadIndex
Unsigned integer to index a thread number. The maximum thread number (for each processor) must fit into this type. ๐งต
๐ Enumeration Type Documentation
enum __gnu_parallel::_AlgorithmStrategy
Strategies for run-time algorithm selection:
enum __gnu_parallel::_FindAlgorithm
Find algorithms:
enum __gnu_parallel::_MultiwayMergeAlgorithm
Merging algorithms:
enum __gnu_parallel::_Parallelism
Run-time equivalents for the compile-time tags. this is how you say "compile-time vibe" at runtime ๐
Enumerator
sequentialโ Not parallel. just you and the algorithm, alone together ๐parallel_unbalancedโ Parallel unbalanced (equal-sized chunks). everyone gets the same size plate, even if some are starving ๐ฝ๏ธparallel_balancedโ Parallel balanced (work-stealing). stealing work but make it a feature โจparallel_omp_loopโ Parallel with OpenMP dynamic load-balancing. ๐parallel_omp_loop_staticโ Parallel with OpenMP static load-balancing.parallel_taskqueueโ Parallel with OpenMP taskqueue construct. the queue is queuing ๐
enum __gnu_parallel::_PartialSumAlgorithm
Partial sum algorithms: recursive, linear.
enum __gnu_parallel::_SortAlgorithm
Sorting algorithms:
enum __gnu_parallel::_SplittingAlgorithm
Sorting/merging algorithms: sampling, __exact. two flavors, pick your fighter ๐ฅ
โญ Function Documentation
template<typename _RAIter , typename _DifferenceTp > void __gnu_parallel::__calc_borders (_RAIter __elements, _DifferenceTp __length, _DifferenceTp * __off)
Precalculate __advances for Knuth-Morris-Pratt algorithm. yes THE Knuth-Morris-Pratt, we love a legendary string-searching moment ๐
Parameters
__elementsโ Begin iterator of sequence to search for.__lengthโ Length of sequence to search for.__offโ Returned__offsets.
Referenced by __search_template().
template<typename _Tp > bool __gnu_parallel::__compare_and_swap (volatile _Tp * __ptr, _Tp __comparand, _Tp __replacement) [inline]
Compare-and-swap. Compare *__ptr and __comparand. If equal, let *__ptr=__replacement and return true, return false otherwise. literally the "are we the same? then swap, slay" of atomic operations ๐
Parameters
__ptrโ Pointer to signed integer.__comparandโ Compare value.__replacementโ Replacement value.
Referenced by __parallel_partition(), __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::pop_back(), and __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::pop_front().
void __gnu_parallel::__decode2 (_CASable __x, int & __a, int & __b) [inline]
Decode two integers from one gnu_parallel::_CASable. two-for-one, we love a bundle deal ๐
Okay so the parameter deets for that decode one, bestie โ here's what goes where ๐
Parameters:
__xโ the__gnu_parallel::_CASableyou're pulling integers out of. It's giving "the source of truth" โจ__aโ first integer, decoded from the most-significant_CASable_bits/2bits of__x__bโ second integer, encoded in the least-significant_CASable_bits/2bits of__x
See also: __encode2 (its whole mirror-image moment ๐ช)
References: _CASable_bits, and _CASable_mask.
Referenced by: __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::pop_back(), __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::pop_front(), and __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::push_front().
๐ __determine_samples โ picking the samples, lowkey iconic
template<typename _RAIter , typename _DifferenceTp > void
__gnu_parallel::__determine_samples (_PMWMSSortingData< _RAIter > *
__sd, _DifferenceTp __num_samples)
Literally just: select _M_samples from a sequence. That's the whole vibe check โ
Parameters:
__sdโ pointer to the algorithm data. The_Resultgets placed in__sd->_M_samples, no cap ๐ซถ__num_samplesโ how many_M_samplesyou want to select
References: __equally_split(), __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_samples, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_source, and __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_starts.
๐ __encode2 โ squish two ints into one, [inline]
_CASable __gnu_parallel::__encode2 (int __a, int __b) [inline]
Encode two integers into one gnu_parallel::_CASable. Two besties, one slot โ it's giving compression ๐
Parameters:
__aโ first integer, encoded in the most-significant_CASable_bits/2bits__bโ second integer, encoded in the least-significant_CASable_bits/2bits
Returns: the value encoding __a and __b โจ
See also: __decode2 (the un-squisher)
References: _CASable_bits.
Referenced by: __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::_RestrictedBoundedConcurrentQueue(), __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::pop_back(), __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::pop_front(), and __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::push_front().
๐ฆ __equally_split โ slice it into (almost) equal parts, periodt
template<typename _DifferenceType , typename _OutputIterator >
_OutputIterator __gnu_parallel::__equally_split (_DifferenceType __n,
_ThreadIndex __num_threads, _OutputIterator __s)
So this is the function that splits a sequence into parts of almost equal size. The resulting sequence __s of length __num_threads+1 contains the splitting positions when splitting the range [0,__n) into parts of almost equal size (plus minus 1). The first entry is 0, the last one is n. Heads up though โ there may result empty parts, and that's just a thing that happens ๐
Parameters:
__nโ number of elements__num_threadsโ number of parts__sโ splitters
Returns: end of __splitter sequence, i.e. __s+__num_threads+1
Referenced by: __determine_samples(), __find_template(), __parallel_partial_sum_linear(), __parallel_unique_copy(), __search_template(), and multiway_merge_exact_splitting().
โญ __equally_split_point โ the single split point you asked for
template<typename _DifferenceType > _DifferenceType
__gnu_parallel::__equally_split_point (_DifferenceType __n, _ThreadIndex
__num_threads, _ThreadIndex __thread_no)
Same splitting-a-sequence-into-parts-of-almost-equal-size energy, but this one hands you back the position of the splitting point between thread number __thread_no (included) and thread number __thread_no+1 (excluded). One number, zero drama ๐
Parameters:
__nโ number of elements__num_threadsโ number of parts__thread_noโ number of threads
Returns: the splitting point ๐ฏ
Referenced by: __for_each_template_random_access_ed().
๐ฅ __fetch_and_add โ atomic add, [inline]
template<typename _Tp > _Tp __gnu_parallel::__fetch_and_add (volatile _Tp *
__ptr, _Tp __addend) [inline]
Add a value to a variable, atomically. Like, nobody can sneak in and ruin the math mid-update. Main character energy for real ๐
Parameters:
__ptrโ pointer to a signed integer__addendโ value to add
Referenced by: __parallel_partition(), and __gnu_parallel::_RestrictedBoundedConcurrentQueue< _Tp >::push_front().
๐ง __find_template โ parallel std::find, the switchboard edition, [inline]
template<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename
_Selector > std::pair< _RAIter1, _RAIter2 >
__gnu_parallel::__find_template (_RAIter1 __begin1, _RAIter1 __end1,
_RAIter2 __begin2, _Pred __pred, _Selector __selector) [inline]
Parallel std::find, and it's the switch for different algorithms. She picks the strategy, babes โจ
Parameters:
__begin1โ begin iterator of first sequence__end1โ end iterator of first sequence__begin2โ begin iterator of second sequence. Must have same length as first sequence โ ๏ธ__predโ find predicate__selectorโ_Functionality(e. g.std::find_if(),std::equal(),...)
Returns: place of finding in both sequences ๐ซถ
References: __find_template(), and __gnu_parallel::_Settings::get().
Referenced by: __find_template().
๐ __find_template โ constant size blocks variant
template<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename
_Selector > std::pair< _RAIter1, _RAIter2 >
__gnu_parallel::__find_template (_RAIter1 __begin1, _RAIter1 __end1,
_RAIter2 __begin2, _Pred __pred, _Selector __selector,
constant_size_blocks_tag)
Parallel std::find, constant block size variant. Same search, different chunking strategy ๐
Parameters:
__begin1โ begin iterator of first sequence__end1โ end iterator of first sequence__begin2โ begin iterator of second sequence. Second__sequencemust have same length as first sequence__predโ find predicate__selectorโ_Functionality(e. g.std::find_if(),std::equal(),...)
Returns: place of finding in both sequences
See also: __gnu_parallel::_Settings::find_sequential_search_size
__gnu_parallel::_Settings::find_block_size
There are two main differences between the growing blocks and the constant-size blocks variants, and yes you need both of them in your head:
- For GB, the block size grows; for CSB, the block size is fixed.
- For GB, the blocks are allocated dynamically; for CSB, the blocks are allocated in a predetermined manner, namely spacial round-robin.
References: _GLIBCXX_CALL, __gnu_parallel::_Settings::find_initial_block_size, __gnu_parallel::_Settings::find_sequential_search_size, std::pair< _T1, _T2 >::first, and __gnu_parallel::_Settings::get().
๐ธ __find_template โ equal splitting variant
template<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename
_Selector > std::pair< _RAIter1, _RAIter2 >
__gnu_parallel::__find_template (_RAIter1 __begin1, _RAIter1 __end1,
_RAIter2 __begin2, _Pred __pred, _Selector __selector, equal_split_tag)
Parallel std::find, equal splitting variant. Everyone gets the same slice, fair and square ๐ค
Parameters:
__begin1โ begin iterator of first sequence__end1โ end iterator of first sequence__begin2โ begin iterator of second sequence. Second__sequencemust have same length as first sequence__predโ find predicate__selectorโ_Functionality(e. g.std::find_if(),std::equal(),...)
Returns: place of finding in both sequences
References: __equally_split(), and _GLIBCXX_CALL.
๐ __find_template โ growing blocks variant
template<typename _RAIter1 , typename _RAIter2 , typename _Pred , typename
_Selector > std::pair< _RAIter1, _RAIter2 >
__gnu_parallel::__find_template (_RAIter1 __begin1, _RAIter1 __end1,
_RAIter2 __begin2, _Pred __pred, _Selector __selector,
growing_blocks_tag)
Parallel std::find, growing block size variant. The blocks start small and justโฆ grow up ๐ญ๐
Parameters:
__begin1โ begin iterator of first sequence__end1โ end iterator of first sequence__begin2โ begin iterator of second sequence. Second__sequencemust have same length as first sequence__predโ find predicate__selectorโ_Functionality(e. g.std::find_if(),std::equal(),...)
Returns: place of finding in both sequences
See also: __gnu_parallel::_Settings::find_sequential_search_size
__gnu_parallel::_Settings::find_scale_factor
The same two main differences between growing blocks and constant-size blocks, once more for the people in the back:
- For GB, the block size grows; for CSB, the block size is fixed.
- For GB, the blocks are allocated dynamically; for CSB, the blocks are allocated in a predetermined manner, namely spacial round-robin.
References: _GLIBCXX_CALL, __gnu_parallel::_Settings::find_scale_factor, __gnu_parallel::_Settings::find_sequential_search_size, std::pair< _T1, _T2 >::first, and __gnu_parallel::_Settings::get().
๐ __for_each_template_random_access โ pick your algorithm by tag
template<typename _IIter , typename _UserOp , typename _Functionality ,
typename _Red , typename _Result > _UserOp
__gnu_parallel::__for_each_template_random_access (_IIter __begin,
_IIter __end, _UserOp __user_op, _Functionality & __functionality, _Red
__reduction, _Result __reduction_start, _Result & __output, typename
std::iterator_traits< _IIter >::difference_type __bound, _Parallelism
__parallelism_tag)
Choose the desired algorithm by evaluating __parallelism_tag. She reads the tag, she picks the whole strategy โ it's giving "I contain multitudes" ๐
Parameters:
__beginโ begin iterator of input sequence__endโ end iterator of input sequence__user_opโ a user-specified functor (comparator, predicate, associative operator,...)__functionalityโ functor to process an element with__user_op(depends on desired functionality, e. g. accumulate, for_each,...__reductionโ reduction functor__reduction_startโ initial value for reduction__outputโ output iterator__boundโ maximum number of elements processed__parallelism_tagโ parallelization method
References: __for_each_template_random_access_ed(), __for_each_template_random_access_omp_loop(), __for_each_template_random_access_workstealing(), parallel_omp_loop, parallel_omp_loop_static, and parallel_unbalanced.
๐ __for_each_template_random_access_ed โ embarrassingly parallel, hand-crafted
template<typename _RAIter , typename _Op , typename _Fu , typename _Red ,
typename _Result > _Op
__gnu_parallel::__for_each_template_random_access_ed (_RAIter __begin,
_RAIter __end, _Op __o, _Fu & __f, _Red __r, _Result __base, _Result &
__output, typename std::iterator_traits< _RAIter >::difference_type
__bound)
Embarrassingly parallel algorithm for random access iterators, using hand-crafted parallelization by equal splitting the work. Hand-crafted!! Like a lil artisanal parallel algorithm, we love her ๐งโจ
Parameters:
__beginโ begin iterator of element sequence__endโ end iterator of element sequence__oโ user-supplied functor (comparator, predicate, adding functor, ...)__fโ functor to 'process' an element with__op(depends on desired functionality, e. g. forstd::for_each(), ...)__rโ functor to 'add' a single__resultto the already processed elements (depends on functionality)__baseโ base value for reduction__outputโ pointer to position where final result is written to__boundโ maximum number of elements processed (e. g. forstd::count_n())
Returns: user-supplied functor (that may contain a part of the result) ๐
References: __equally_split_point().
Referenced by: __for_each_template_random_access().
๐ __for_each_template_random_access_omp_loop
template<typename _RAIter , typename _Op , typename _Fu , typename _Red ,
typename _Result > _Op
__gnu_parallel::__for_each_template_random_access_omp_loop (_RAIter
__begin, _RAIter __end, _Op __o, _Fu & __f, _Red __r, _Result __base,
_Result & __output, typename std::iterator_traits< _RAIter
>::difference_type __bound)
Okay bestie, this one is the embarrassingly parallel algorithm for random access iterators, and it does the whole thing with an OpenMP for loop. It's giving "I have never known struggle" energy honestly ๐
Parameters โ let's go through them, no skips:
__beginโ begin iterator of element sequence.__endโ end iterator of element sequence.__oโ your user-supplied functor (comparator, predicate, adding functor, etc.).__fโ functor to process an element with__op(depends on what functionality you want, e.g. forstd::for_each(), ...).__rโ functor to add a single__resultto the already processed elements (depends on functionality).__baseโ base value for reduction.__outputโ pointer to the position where the final result is written to.__boundโ maximum number of elements processed (e.g. forstd::count_n()).
Returns โ your user-supplied functor, which may contain a part of the result. โจ
Referenced by __for_each_template_random_access().
๐ฆ __for_each_template_random_access_omp_loop_static
template<typename _RAIter , typename _Op , typename _Fu , typename _Red ,
typename _Result > _Op
__gnu_parallel::__for_each_template_random_access_omp_loop_static
(_RAIter __begin, _RAIter __end, _Op __o, _Fu & __f, _Red __r, _Result
__base, _Result & __output, typename std::iterator_traits< _RAIter
>::difference_type __bound)
Same embarrassingly parallel algorithm for random access iterators, except it's an OpenMP for loop with static scheduling. Same vibes, more predictable, iykyk ๐
Parameters:
__beginโ begin iterator of element sequence.__endโ end iterator of element sequence.__oโ user-supplied functor (comparator, predicate, adding functor, ...).__fโ functor to process an element with__op(depends on desired functionality, e.g. forstd::for_each(), ...).__rโ functor to add a single__resultto the already processed__elements(depends on functionality).__baseโ base value for reduction.__outputโ pointer to position where final result is written to.__boundโ maximum number of elements processed (e.g. forstd::count_n()).
Returns โ the user-supplied functor, may contain a part of the result ๐
๐ฅ __for_each_template_random_access_workstealing
template<typename _RAIter , typename _Op , typename _Fu , typename _Red ,
typename _Result > _Op
__gnu_parallel::__for_each_template_random_access_workstealing (_RAIter
__begin, _RAIter __end, _Op __op, _Fu & __f, _Red __r, _Result __base,
_Result & __output, typename std::iterator_traits< _RAIter
>::difference_type __bound)
The work stealing algorithm for random access iterators, and she is so efficient it hurts โ uses O(1) additional memory, no cap. Synchronization at job lists is done with atomic operations, which is basically the flex of the century ๐
Parameters:
__beginโ begin iterator of element sequence.__endโ end iterator of element sequence.__opโ user-supplied functor (comparator, predicate, adding functor, ...).__fโ functor to process an element with__op(depends on desired functionality, e.g. forstd::for_each(), ...).__rโ functor to add a single__resultto the already processed elements (depends on functionality).__baseโ base value for reduction.__outputโ pointer to position where final result is written to.__boundโ maximum number of elements processed (e.g. forstd::count_n()).
Returns โ the user-supplied functor (may contain a part of the result).
References: __yield(), _GLIBCXX_CALL, __gnu_parallel::_Job< _DifferenceTp >::_M_first, __gnu_parallel::_Job< _DifferenceTp >::_M_last, __gnu_parallel::_Job< _DifferenceTp >::_M_load, __gnu_parallel::_Settings::cache_line_size, __gnu_parallel::_Settings::get(), and min().
Referenced by __for_each_template_random_access().
โญ __is_sorted
template<typename _IIter , typename _Compare > bool
__gnu_parallel::__is_sorted (_IIter __begin, _IIter __end, _Compare
__comp)
A little vibe check: is [__begin, __end) sorted according to __comp? That's literally it, that's the whole job ๐ซถ
Parameters:
__beginโ begin iterator of sequence.__endโ end iterator of sequence.__compโ comparator.
Returns โ true if sorted, false otherwise.
Referenced by __sequential_multiway_merge(), multiway_merge_loser_tree_sentinel(), and parallel_multiway_merge().
๐ง __median_of_three_iterators
template<typename _RAIter , typename _Compare > _RAIter
__gnu_parallel::__median_of_three_iterators (_RAIter __a, _RAIter __b,
_RAIter __c, _Compare __comp)
Computes the median of three referenced elements, according to __comp. Three candidates walk in, one middle child walks out ๐ญ
Parameters:
__aโ first iterator.__bโ second iterator.__cโ third iterator.__compโ comparator.
Referenced by __qsb_divide().
๐ __merge_advance
template<typename _RAIter1 , typename _RAIter2 , typename _OutputIterator ,
typename _DifferenceTp , typename _Compare > _OutputIterator
__gnu_parallel::__merge_advance (_RAIter1 & __begin1, _RAIter1 __end1,
_RAIter2 & __begin2, _RAIter2 __end2, _OutputIterator __target,
_DifferenceTp __max_length, _Compare __comp) [inline]
A merge routine that can only merge the __max_length smallest elements. The __begin iterators get advanced accordingly, so heads up: they might not reach __end, in contrast to the usual variant. It also does a static switch on whether to use the conditional-move variant. She contains multitudes โจ
Parameters:
__begin1โ begin iterator of first sequence.__end1โ end iterator of first sequence.__begin2โ begin iterator of second sequence.__end2โ end iterator of second sequence.__targetโ target begin iterator.__max_lengthโ maximum number of elements to merge.__compโ comparator.
Returns โ output end iterator.
References __merge_advance_movc(), and _GLIBCXX_CALL.
Referenced by __parallel_merge_advance(), and __sequential_multiway_merge().
๐ธ __merge_advance_movc
template<typename _RAIter1 , typename _RAIter2 , typename _OutputIterator ,
typename _DifferenceTp , typename _Compare > _OutputIterator
__gnu_parallel::__merge_advance_movc (_RAIter1 & __begin1, _RAIter1
__end1, _RAIter2 & __begin2, _RAIter2 __end2, _OutputIterator __target,
_DifferenceTp __max_length, _Compare __comp)
Another merge-only-the-__max_length-smallest-elements routine, and the __begin iterators advance the same way โ again, they might not reach __end, unlike the usual variant. The difference? The code is specially designed so the compiler can generate conditional moves instead of branches. It's giving "I was built different on purpose" ๐
Parameters:
__begin1โ begin iterator of first sequence.__end1โ end iterator of first sequence.__begin2โ begin iterator of second sequence.__end2โ end iterator of second sequence.__targetโ target begin iterator.__max_lengthโ maximum number of elements to merge.__compโ comparator.
Returns โ output end iterator.
Referenced by __merge_advance().
๐ __merge_advance_usual
template<typename _RAIter1 , typename _RAIter2 , typename _OutputIterator ,
typename _DifferenceTp , typename _Compare > _OutputIterator
__gnu_parallel::__merge_advance_usual (_RAIter1 & __begin1, _RAIter1
__end1, _RAIter2 & __begin2, _RAIter2 __end2, _OutputIterator __target,
_DifferenceTp __max_length, _Compare __comp)
The plain-jane one: merges only the __max_length smallest elements, the __begin iterators get advanced accordingly and might not reach __end, in contrast to the usual variant. (Yes, the description says "in contrast to the usual variant" and this is the usual variant, don't come for me, I'm just the messenger ๐)
Parameters:
__begin1โ begin iterator of first sequence.__end1โ end iterator of first sequence.__begin2โ begin iterator of second sequence.__end2โ end iterator of second sequence.__targetโ target begin iterator.__max_lengthโ maximum number of elements to merge.__compโ comparator.
Returns โ output end iterator.
๐ __parallel_merge_advance (first overload)
template<typename _RAIter1 , typename _RAIter3 , typename _Compare >
_RAIter3 __gnu_parallel::__parallel_merge_advance (_RAIter1 & __begin1,
_RAIter1 __end1, _RAIter1 & __begin2, _RAIter1 __end2, _RAIter3
__target, typename std::iterator_traits< _RAIter1 >::difference_type
__max_length, _Compare __comp) [inline]
The parallel merge routine, merging only the __max_length smallest elements. The __begin iterators are advanced accordingly and might not reach __end, in contrast to the usual variant โ and the whole functionality is projected onto parallel_multiway_merge. Fancy, honestly ๐ฅ
Parameters:
__begin1โ begin iterator of first sequence.__end1โ end iterator of first sequence.__begin2โ begin iterator of second sequence.__end2โ end iterator of second sequence.__targetโ target begin iterator.__max_lengthโ maximum number of elements to merge.__compโ comparator.
Returns โ output end iterator.
References multiway_merge_exact_splitting(), and parallel_multiway_merge().
๐ซถ __parallel_merge_advance (second overload)
template<typename _RAIter1 , typename _RAIter2 , typename _RAIter3 ,
typename _Compare > _RAIter3 __gnu_parallel::__parallel_merge_advance
(_RAIter1 & __begin1, _RAIter1 __end1, _RAIter2 & __begin2, _RAIter2
__end2, _RAIter3 __target, typename std::iterator_traits< _RAIter1
>::difference_type __max_length, _Compare __comp) [inline]
Samesies name, different template params โ and this one is the fallback to sequential in case the iterators of the two input sequences are of different types. Like, it tried parallelism, saw a type mismatch, and said "bestie I got you, we're doing this the chill way" ๐
Parameters:
__begin1โ begin iterator of first sequence.__end1โ end iterator of first sequence.__begin2โ begin iterator of second sequence.__end2โ end iterator of second sequence.__targetโ target begin iterator.__max_lengthโ maximum number of elements to merge.__compโ comparator.
Returns โ output end iterator.
References __merge_advance().
๐ __parallel_nth_element
template<typename _RAIter , typename _Compare > void
__gnu_parallel::__parallel_nth_element (_RAIter __begin, _RAIter __nth,
_RAIter __end, _Compare __comp)
The parallel implementation of std::nth_element(). She finds the one โจiconicโจ element that has to be in a specific position and makes it happen.
Parameters:
__beginโ begin iterator of input sequence.__nthโ Iterator of element that must be in position afterwards.__endโ end iterator of input sequence.__compโ comparator.
References __parallel_partition(), _GLIBCXX_CALL, __gnu_parallel::_Settings::get(), std::max(), __gnu_parallel::_Settings::nth_element_minimal_n, and __gnu_parallel::_Settings::partition_minimal_n.
Referenced by __parallel_partial_sort().
๐ __parallel_partial_sort
template<typename _RAIter , typename _Compare > void
__gnu_parallel::__parallel_partial_sort (_RAIter __begin, _RAIter
__middle, _RAIter __end, _Compare __comp)
The parallel implementation of std::partial_sort() โ sort everything up to __middle and then just vibe ๐ธ
Parameters:
__beginโ begin iterator of input sequence.__middleโ sort until this position.__endโ end iterator of input sequence.__compโ comparator.
References __parallel_nth_element().
๐ __parallel_partial_sum
template<typename _IIter, typename _OutputIterator, typename _BinaryOperation>
_OutputIterator
__gnu_parallel::__parallel_partial_sum(_IIter __begin, _IIter __end,
_OutputIterator __result,
_BinaryOperation __bin_op)
okay so bestie, this is the parallel partial sum โ front to __end, and it's giving "prefix sums but make it multithreaded" โจ
Parameters
__beginโ begin iterator of input sequence ๐__endโ end iterator of input sequence__resultโ begin iterator of output sequence__bin_opโ associative binary function (yes it gotta be associative, no cap)
Returns End iterator of output sequence ๐
References: __parallel_partial_sum_linear(), _GLIBCXX_CALL, and __gnu_parallel::_Settings::get().
๐ง __parallel_partial_sum_basecase
template<typename _IIter, typename _OutputIterator, typename _BinaryOperation>
_OutputIterator
__gnu_parallel::__parallel_partial_sum_basecase(_IIter __begin, _IIter __end,
_OutputIterator __result,
_BinaryOperation __bin_op,
typename std::iterator_traits<_IIter>::value_type __value)
the base case prefix sum routine, lowkey the little worker bee of the whole thing ๐
Parameters
__beginโ begin iterator of input sequence__endโ end iterator of input sequence__resultโ begin iterator of output sequence__bin_opโ associative binary function__valueโ start value. Must be passed since the neutral element is unknown in general ๐ (like, we literally can't guess it for you)
Returns End iterator of output sequence ๐ซ
Referenced by __parallel_partial_sum_linear().
๐ธ __parallel_partial_sum_linear
template<typename _IIter, typename _OutputIterator, typename _BinaryOperation>
_OutputIterator
__gnu_parallel::__parallel_partial_sum_linear(_IIter __begin, _IIter __end,
_OutputIterator __result,
_BinaryOperation __bin_op,
typename std::iterator_traits<_IIter>::difference_type __n)
the parallel partial sum implementation โ two-phase approach, no recursion ๐ it's giving "we do it in two passes and we don't call ourselves, periodt"
Parameters
__beginโ begin iterator of input sequence__endโ end iterator of input sequence__resultโ begin iterator of output sequence__bin_opโ associative binary function__nโ length of sequence ๐
Returns End iterator of output sequence โญ
References: __equally_split(), __parallel_partial_sum_basecase(), __gnu_parallel::_Settings::get(), and __gnu_parallel::_Settings::partial_sum_dilation.
Referenced by __parallel_partial_sum().
๐ฆ __parallel_partition
template<typename _RAIter, typename _Predicate>
std::iterator_traits<_RAIter>::difference_type
__gnu_parallel::__parallel_partition(_RAIter __begin, _RAIter __end,
_Predicate __pred,
_ThreadIndex __num_threads)
the parallel implementation of std::partition โ splitting the crowd into "yass" and "nah" ๐
Parameters
__beginโ begin iterator of input sequence to split__endโ end iterator of input sequence to split__predโ partition predicate, possibly including some kind of pivot ๐ฏ__num_threadsโ maximum number of threads to use for this task
Returns Number of elements not fulfilling the predicate (so like, count of the leftovers) ๐
References: __compare_and_swap(), __fetch_and_add(), _GLIBCXX_CALL, _GLIBCXX_VOLATILE, __gnu_parallel::_Settings::get(), __gnu_parallel::_Settings::partition_chunk_share, and __gnu_parallel::_Settings::partition_chunk_size.
Referenced by __parallel_nth_element(), __parallel_sort_qs_divide(), and __qsb_divide().
๐ __parallel_random_shuffle
template<typename _RAIter, typename _RandomNumberGenerator>
void
__gnu_parallel::__parallel_random_shuffle(_RAIter __begin, _RAIter __end,
_RandomNumberGenerator __rng = _RandomNumber()) // [inline]
the parallel random public call โ this is the one you actually call, bestie, it's the front door ๐ชโจ
Parameters
__beginโ begin iterator of sequence__endโ end iterator of sequence__rngโ random number generator to use (defaults to_RandomNumber())
References: __parallel_random_shuffle_drs().
๐ฅ __parallel_random_shuffle_drs
template<typename _RAIter, typename _RandomNumberGenerator>
void
__gnu_parallel::__parallel_random_shuffle_drs(_RAIter __begin, _RAIter __end,
typename std::iterator_traits<_RAIter>::difference_type __n,
_ThreadIndex __num_threads,
_RandomNumberGenerator &__rng)
the main parallel random shuffle step โ the real main-character energy of this shuffle situation ๐
Parameters
__beginโ begin iterator of sequence__endโ end iterator of sequence__nโ length of sequence__num_threadsโ number of threads to use__rngโ random number generator to use
References:
__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::__bins_end__parallel_random_shuffle_drs_pu()__rd_log2()__round_up_to_pow2()__sequential_random_shuffle()_GLIBCXX_CALL__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_bin_proc__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_bins_begin__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_dist__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_num_bins__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_num_bits__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_num_threads__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_sd__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_seed__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_starts__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_temporaries__gnu_parallel::_Settings::get()__gnu_parallel::_Settings::L2_cache_sizestd::min()__gnu_parallel::_Settings::TLB_size
Referenced by __parallel_random_shuffle().
๐ __parallel_random_shuffle_drs_pu
template<typename _RAIter, typename _RandomNumberGenerator>
void
__gnu_parallel::__parallel_random_shuffle_drs_pu(_DRSSorterPU<_RAIter, _RandomNumberGenerator> *__pus)
the random shuffle code executed by each thread โ like, every thread grabs its own lil to-do list and vibes ๐ง
Parameters
__pusโ array of thread-local data records
References:
__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::__bins_end__random_number_pow2()__sequential_random_shuffle()__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_bin_proc__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_bins_begin__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_dist__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_num_bins__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_num_bits__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_num_threads__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_sd__gnu_parallel::_DRSSorterPU<_RAIter, _RandomNumberGenerator>::_M_seed__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_source__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_starts__gnu_parallel::_DRandomShufflingGlobalData<_RAIter>::_M_temporariesstd::partial_sum()
Referenced by __parallel_random_shuffle_drs().
๐ __parallel_sort โ the overload era
bestie, there are seven overloads of this and they're all just picking a different sorting algorithm based on the tag you hand them. same params, same template param, different vibe check on __parallelism ๐ซถ
Every single one of them takes:
__beginโ begin iterator of input sequence__endโ end iterator of input sequence__compโ comparator
and has the template parameter:
__stableโ sort stable
__parallel_sort with balanced_quicksort_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
balanced_quicksort_tag __parallelism) // [inline]
Choose balanced quicksort for parallel sorting. ๐ฅ balanced = the responsible quicksort, fr fr.
References: __gnu_parallel::parallel_tag::__get_num_threads(), __parallel_sort_qsb(), and _GLIBCXX_CALL.
__parallel_sort with default_parallel_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
default_parallel_tag __parallelism) // [inline]
Choose multiway mergesort with exact splitting, for parallel sorting. the default default, iconic โจ
References: __gnu_parallel::parallel_tag::__get_num_threads(), and _GLIBCXX_CALL.
__parallel_sort with multiway_mergesort_exact_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
multiway_mergesort_exact_tag __parallelism) // [inline]
Choose multiway mergesort with exact splitting, for parallel sorting. yes it's the same description as above, that's literally what the page says, don't come for me ๐
References: __gnu_parallel::parallel_tag::__get_num_threads(), and _GLIBCXX_CALL.
__parallel_sort with multiway_mergesort_sampling_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
multiway_mergesort_sampling_tag __parallelism) // [inline]
Choose multiway mergesort with splitting by sampling, for parallel sorting. sampling the data first, very "let me get a feel for the crowd" ๐
References: __gnu_parallel::parallel_tag::__get_num_threads(), and _GLIBCXX_CALL.
__parallel_sort with multiway_mergesort_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
multiway_mergesort_tag __parallelism) // [inline]
Choose multiway mergesort, splitting variant at run-time, for parallel sorting. so it decides the splitting situation live โ main character improvisation ๐
References: __gnu_parallel::parallel_tag::__get_num_threads(), _GLIBCXX_CALL, and __gnu_parallel::_Settings::get().
__parallel_sort with parallel_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
parallel_tag __parallelism) // [inline]
Choose a parallel sorting algorithm. just, like, one of them. the algorithm chooses its own destiny ๐ฆ
References: __gnu_parallel::parallel_tag::__get_num_threads(), __parallel_sort_qs(), __parallel_sort_qsb(), _GLIBCXX_CALL, and __gnu_parallel::_Settings::get().
__parallel_sort with quicksort_tag
template<bool __stable, typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort(_RAIter __begin, _RAIter __end,
_Compare __comp,
quicksort_tag __parallelism) // [inline]
Choose quicksort for parallel sorting. the classic, the legend, the one everybody knows โญ
References: __gnu_parallel::parallel_tag::__get_num_threads(), __parallel_sort_qs(), and _GLIBCXX_CALL.
โก __parallel_sort_qs
template<typename _RAIter, typename _Compare>
void
__gnu_parallel::__parallel_sort_qs(_RAIter __begin, _RAIter __end,
_Compare __comp,
_ThreadIndex __num_threads)
the unbalanced quicksort main call โ no balancing, all chaos, still slaps ๐ฅ
Parameters
__beginโ begin iterator of input sequence__endโ end iterator input sequence, ignored ๐ (yes, literally ignored, that's what it says)__compโ comparator__num_threadsโ number of threads that are allowed to work on this part
References: __parallel_sort_qs_conquer(), and _GLIBCXX_CALL.
๐ __parallel_sort_qs_conquer
template<typename _RAIter , typename _Compare > void
__gnu_parallel::__parallel_sort_qs_conquer (_RAIter __begin, _RAIter __end,
_Compare __comp, _ThreadIndex __num_threads)
Unbalanced quicksort conquer step โจ โ literally the part where it goes and actually sorts the pieces.
Parameters
__beginโ begin iterator of subsequence.__endโ end iterator of subsequence.__compโ comparator.__num_threadsโ number of threads that are allowed to work on this part.
References: __parallel_sort_qs_conquer(), __parallel_sort_qs_divide(), and __gnu_parallel::_Settings::get().
Referenced by: __parallel_sort_qs(), and __parallel_sort_qs_conquer().
๐ __parallel_sort_qs_divide
template<typename _RAIter , typename _Compare > std::iterator_traits<
_RAIter >::difference_type __gnu_parallel::__parallel_sort_qs_divide
(_RAIter __begin, _RAIter __end, _Compare __comp,
typename std::iterator_traits< _RAIter >::difference_type __pivot_rank,
typename std::iterator_traits< _RAIter >::difference_type __num_samples,
_ThreadIndex __num_threads)
Unbalanced quicksort divide step ๐ the part that picks the pivot and splits everything up.
Parameters
__beginโ begin iterator of subsequence.__endโ end iterator of subsequence.__compโ comparator.__pivot_rankโ desired__rankof the pivot.__num_samplesโ choose pivot from that many samples.__num_threadsโ number of threads that are allowed to work on this part.
References: __parallel_partition(), and std::min().
Referenced by: __parallel_sort_qs_conquer().
๐ __parallel_sort_qsb
template<typename _RAIter , typename _Compare > void
__gnu_parallel::__parallel_sort_qsb (_RAIter __begin, _RAIter __end,
_Compare __comp, _ThreadIndex __num_threads)
Top-level quicksort routine ๐ the main character of the quicksort situation, no cap.
Parameters
__beginโ begin iterator of sequence.__endโ end iterator of sequence.__compโ comparator.__num_threadsโ number of threads that are allowed to work on this part.
References: __qsb_conquer(), __rd_log2(), _GLIBCXX_CALL, and __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_elements_leftover.
Referenced by: __parallel_sort(), and __parallel_sort().
๐ฆ __parallel_unique_copy (the no-predicate one)
template<typename _IIter , class _OutputIterator > _OutputIterator
__gnu_parallel::__parallel_unique_copy (_IIter __first, _IIter __last,
_OutputIterator __result) [inline]
Parallel std::unique_copy(), without explicit equality predicate ๐ธ โ like, it just assumes == and vibes.
Parameters
__firstโ begin iterator of input sequence.__lastโ end iterator of input sequence.__resultโ begin iterator of result__sequence.
Returns: end iterator of result __sequence.
References: __parallel_unique_copy().
๐ฆ __parallel_unique_copy (the one with a predicate)
template<typename _IIter , class _OutputIterator , class _BinaryPredicate >
_OutputIterator __gnu_parallel::__parallel_unique_copy (_IIter __first,
_IIter __last, _OutputIterator __result, _BinaryPredicate __binary_pred)
Parallel std::unique_copy(), w/__o explicit equality predicate ๐ โ yes bestie, you get to bring your own "are these the same" rules. (That w/__o is exactly how the original spells it, iconic typo energy, we keep it fr.)
Parameters
__firstโ begin iterator of input sequence.__lastโ end iterator of input sequence.__resultโ begin iterator of result__sequence.__binary_predโ equality predicate.
Returns: end iterator of result __sequence.
References: __equally_split(), and _GLIBCXX_CALL.
Referenced by: __parallel_unique_copy().
๐ __qsb_conquer
template<typename _RAIter , typename _Compare > void
__gnu_parallel::__qsb_conquer (_QSBThreadLocal< _RAIter > ** __tls,
_RAIter __begin, _RAIter __end, _Compare __comp, _ThreadIndex __iam,
_ThreadIndex __num_threads, bool __parent_wait)
Quicksort conquer step โญ the balanced-quicksort version, doing its little recursion thing.
Parameters
__tlsโ array of thread-local storages.__beginโ begin iterator of subsequence.__endโ end iterator of subsequence.__compโ comparator.__iamโ number of the thread processing this function.__num_threadsโ number of threads that are allowed to work on this part.
References: __qsb_conquer(), __qsb_divide(), __qsb_local_sort_with_helping(), __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_elements_leftover, and __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_initial.
Referenced by: __parallel_sort_qsb(), and __qsb_conquer().
๐ __qsb_divide
template<typename _RAIter , typename _Compare > std::iterator_traits<
_RAIter >::difference_type __gnu_parallel::__qsb_divide (_RAIter __begin,
_RAIter __end, _Compare __comp, _ThreadIndex __num_threads)
Balanced quicksort divide step ๐ง the split-up bit, but make it balanced.
Parameters
__beginโ begin iterator of subsequence.__endโ end iterator of subsequence.__compโ comparator.__num_threadsโ number of threads that are allowed to work on this part.
Precondition: (__end-__begin)>=1 โ ๏ธ โ like, there has to be at least one element in there, bestie, don't play.
References: __median_of_three_iterators(), and __parallel_partition().
Referenced by: __qsb_conquer().
๐ __qsb_local_sort_with_helping
template<typename _RAIter , typename _Compare > void
__gnu_parallel::__qsb_local_sort_with_helping (_QSBThreadLocal< _RAIter >
** __tls, _Compare & __comp, _ThreadIndex __iam, bool __wait)
Quicksort step doing load-balanced local sort ๐ฅ โ the name literally says "with helping", it's giving teamwork, it's giving community.
Parameters
__tlsโ array of thread-local storages.__compโ comparator.__iamโ number of the thread processing this function.
References: __yield(), _GLIBCXX_PARALLEL_ASSERTIONS, __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_elements_leftover, __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_initial, __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_leftover_parts, __gnu_parallel::_QSBThreadLocal< _RAIter >::_M_num_threads, __gnu_parallel::_Settings::get(), and __gnu_parallel::_Settings::sort_qsb_base_case_maximal_n.
Referenced by: __qsb_conquer().
๐ __random_number_pow2
template<typename _RandomNumberGenerator > int
__gnu_parallel::__random_number_pow2 (int __logp, _RandomNumberGenerator &
__rng) [inline]
Generate a random number in [0,2^__logp) ๐ฒ โ cute little power-of-two-bounded random, so tidy.
Parameters
__logpโ logarithm (basis 2) of the upper range__bound.__rngโ random number generator to use.
Referenced by: __parallel_random_shuffle_drs_pu(), and __sequential_random_shuffle().
๐ __rd_log2
template<typename _Size > _Size __gnu_parallel::__rd_log2 (_Size __n)
[inline]
Calculates the rounded-down logarithm of __n for base 2 โจ โ floor energy only, we don't round up around here.
Parameters
__nโ argument.
Returns: returns 0 for any argument <1 ๐ yes, even then. Zero. That's the rule.
Referenced by: __gnu_parallel::_LoserTreeBase< _Tp, _Compare >::_LoserTreeBase(), __parallel_random_shuffle_drs(), __parallel_sort_qsb(), __round_up_to_pow2(), __sequential_random_shuffle(), multiseq_partition(), and multiseq_selection().
๐ __round_up_to_pow2
template<typename _Tp > _Tp __gnu_parallel::__round_up_to_pow2 (_Tp __x)
Round up to the next greater power of 2 ๐ซ โ glow-up your integer, basically.
Parameters
__xโ_Integerto round up.
References: __rd_log2().
Referenced by: __parallel_random_shuffle_drs(), __sequential_random_shuffle(), and multiseq_selection().
๐ซถ __search_template
template<typename __RAIter1 , typename __RAIter2 , typename _Pred >
__RAIter1 __gnu_parallel::__search_template (__RAIter1 __begin1,
__RAIter1 __end1, __RAIter2 __begin2, __RAIter2 __end2, _Pred __pred)
Parallel std::search ๐ โ the "where is this thing inside this other thing" situation, but make it threaded.
Parameters
__begin1โ begin iterator of first sequence.__end1โ end iterator of first sequence.__begin2โ begin iterator of second sequence.__end2โ end iterator of second sequence.__predโ find predicate.
Returns: place of finding in first sequences ๐ธ (yes, "sequences" plural, that's the original wording, we keep it).
References: __calc_borders(), __equally_split(), _GLIBCXX_CALL, and std::min().
๐ __sequential_multiway_merge
template<bool __stable, bool __sentinels, typename _RAIterIterator ,
typename _RAIter3 , typename _DifferenceTp , typename _Compare >
_RAIter3 __gnu_parallel::__sequential_multiway_merge (_RAIterIterator
__seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, const
typename std::iterator_traits< typename std::iterator_traits<
_RAIterIterator >::value_type::first_type >::value_type & __sentinel,
_DifferenceTp __length, _Compare __comp)
Sequential multi-way merging switch ๐ The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and runtime settings โ so like, it decides stuff based on vibes (the branching factor) and the actual settings, iykyk.
Parameters
__seqs_beginโ begin iterator of iterator pair input sequence.__seqs_endโ end iterator of iterator pair input sequence.__targetโ begin iterator of output sequence.__compโ comparator.__lengthโ maximum length to merge, possibly larger than the number of elements available.__sentinelโ the sequences have__a__sentinelelement.
Returns: end iterator of output sequence.
References: __is_sorted(), __merge_advance(), _GLIBCXX_CALL, and _GLIBCXX_PARALLEL_LENGTH.
Referenced by: multiway_merge(), and multiway_merge_sentinels().
๐ __sequential_random_shuffle
template<typename _RAIter , typename _RandomNumberGenerator > void
__gnu_parallel::__sequential_random_shuffle (_RAIter __begin, _RAIter __end,
_RandomNumberGenerator & __rng)
Sequential cache-efficient random shuffle ๐ฆ โ shuffling that's nice to your cache, we love a thoughtful icon.
Parameters
__beginโ begin iterator of sequence.__endโ end iterator of sequence.__rngโ random number generator to use.
References: __random_number_pow2(), __rd_log2(), __round_up_to_pow2(), __sequential_random_shuffle(), __gnu_parallel::_Settings::get(), __gnu_parallel::_Settings::L2_cache_size, std::min(), std::partial_sum(), and __gnu_parallel::_Settings::TLB_size.
Referenced by: __parallel_random_shuffle_drs(), __parallel_random_shuffle_drs_pu(), and __sequential_random_shuffle().
๐ __shrink
template<typename _IIter > void __gnu_parallel::__shrink (std::vector<
_IIter > & __os_starts, size_t & __count_to_two, size_t &
__range_length)
Combines two ranges into one and thus halves the number of ranges ๐ฅ โ like merging two group chats into one, except it's ranges.
Parameters
__os_startsโ start positions worked on (oversampled).__count_to_twoโ counts up to2.__range_lengthโ current length of a chunk.
References: std::vector< _Tp, _Alloc >::size().
Referenced by: __shrink_and_double().
๐ __shrink_and_double
template<typename _IIter > void __gnu_parallel::__shrink_and_double
(std::vector< _IIter > & __os_starts, size_t & __count_to_two, size_t &
__range_length, const bool __make_twice)
Shrinks and doubles the ranges ๐ญ yes both, it shrinks and doubles, don't ask, it's a whole thing.
Parameters
__os_startsโ start positions worked on (oversampled).__count_to_twoโ counts up to2.__range_lengthโ current length of a chunk.__make_twiceโ whether the__os_startsis allowed to be grown or not.
References: __shrink(), std::vector< _Tp, _Alloc >::resize(), and std::vector< _Tp, _Alloc >::size().
Referenced by: list_partition().
๐ __yield
void __gnu_parallel::__yield () [inline]
Yield control to another thread, without waiting for the end of the time slice ๐ โ literally "here bestie, you go, I'm not gonna sit here hogging the whole slice."
Referenced by: __for_each_template_random_access_workstealing(), and __qsb_local_sort_with_helping().
๐ list_partition
template<typename _IIter , typename _FunctorType > size_t
__gnu_parallel::list_partition (const _IIter __begin, const _IIter __end,
_IIter * __starts, size_t * __lengths, const int __num_parts,
_FunctorType & __f, int __oversampling = 0)
Splits a sequence given by input iterators into parts of almost equal size ๐ The function needs only one pass over the sequence โ one pass! iconic efficiency, we stan.
Parameters
__beginโ begin iterator of the input sequence, bestie. Like, where the vibe starts โจ__endโ end iterator of the input sequence. The finish line ๐__startsโ the start iterators for the resulting parts, and it's dimension__num_parts+1. Convenience slay:__starts [__num_parts]literally contains the end iterator of the sequence for you ๐__lengthsโ the length of each resulting part.__num_partsโ how many parts you want the sequence split into, no cap.__fโ functor to be applied to each element by traversing__it__oversamplingโ the oversampling factor, and this one's got lore ๐. If it's0, then the partitions will differ in at most$t{thrm{end} - thrm{begin}}$elements. Otherwise, the ratio between the longest and the shortest part is bounded by$1/(thrm{oversampling}
Returns
Length of the whole sequence. That's it, that's the return ๐
References
__shrink_and_double(), and std::vector< _Tp, _Alloc >::size().
template<typename _Tp > const _Tp & __gnu_parallel::max (const _Tp & __a,
const _Tp & __b) [inline]
Equivalent to std::max. Same energy, different namespace, iykyk ๐ธ
template<typename _Tp > const _Tp & __gnu_parallel::min (const _Tp & __a,
const _Tp & __b) [inline]
Equivalent to std::min. Iconic. No notes ๐
Referenced by __for_each_template_random_access_workstealing().
template<typename _RanSeqs , typename _RankType , typename _RankIterator ,
typename _Compare > void __gnu_parallel::multiseq_partition (_RanSeqs
__begin_seqs, _RanSeqs __end_seqs, _RankType __rank, _RankIterator
__begin_offsets, _Compare __comp = std::less< typename
std::iterator_traits<typename
std::iterator_traits<_RanSeqs>::value_type:: first_type>::value_type>())
Okay so this one splits several sorted sequences at a certain global __rank, and the result is a splitting point for each sequence ๐ฅ. The sequences get passed in via a sequence of random-access iterator pairs, and โ important โ none of the sequences may be empty. Empty sequences are not invited to this party ๐
If there are several equal elements across the split, the ones on the __left side will be chosen from sequences with smaller number. Periodt.
Parameters
__begin_seqsโ begin of the sequence of iterator pairs.__end_seqsโ end of the sequence of iterator pairs.__rankโ the global rank to partition at.__begin_offsetsโ a random-access__sequence__beginwhere the__resultwill be stored in. Each element of the sequence is an iterator that points to the first element on the greater part of the respective__sequence. Cute, right? ๐ฆ__compโ the ordering functor, defaults tostd::less<_Tp>.
References
__rd_log2(), _GLIBCXX_CALL, std::distance(), std::priority_queue< _Tp, _Sequence, _Compare >::empty(), std::max(), std::min(), std::priority_queue< _Tp, _Sequence, _Compare >::pop(), std::priority_queue< _Tp, _Sequence, _Compare >::push(), and std::priority_queue< _Tp, _Sequence, _Compare >::top().
Referenced by multiway_merge_exact_splitting().
template<typename _Tp , typename _RanSeqs , typename _RankType , typename
_Compare > _Tp __gnu_parallel::multiseq_selection (_RanSeqs
__begin_seqs, _RanSeqs __end_seqs, _RankType __rank, _RankType &
__offset, _Compare __comp = std::less<_Tp>())
This one selects the element at a certain global __rank from several sorted sequences ๐ฏ. Same deal as before: the sequences get passed via a sequence of random-access iterator pairs, and none of the sequences may be empty. Non-negotiable ๐
Parameters
__begin_seqsโ begin of the sequence of iterator pairs.__end_seqsโ end of the sequence of iterator pairs.__rankโ the global rank to partition at.__offsetโ the rank of the selected element in the global subsequence of elements equal to the selected element. If the selected element is unique, this number is0. Lowkey the most useful little detail here ๐ซถ__compโ the ordering functor, defaults tostd::less.
References
__rd_log2(), __round_up_to_pow2(), _GLIBCXX_CALL, std::distance(), std::priority_queue< _Tp, _Sequence, _Compare >::empty(), std::max(), std::min(), std::priority_queue< _Tp, _Sequence, _Compare >::pop(), std::priority_queue< _Tp, _Sequence, _Compare >::push(), and std::priority_queue< _Tp, _Sequence, _Compare >::top().
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
__gnu_parallel::multiway_merge (_RAIterPairIterator __seqs_begin,
_RAIterPairIterator __seqs_end, _RAIterOut __target, _DifferenceTp
__length, _Compare __comp, __gnu_parallel::sequential_tag)
Multiway Merge Frontend โจ โ the main character of this whole section, honestly. Merge the sequences specified by seqs_begin and __seqs_end into __target.
__seqs_begin and __seqs_end must point to a sequence of pairs. These pairs must contain an iterator to the beginning of a sequence in their first entry and an iterator the _M_end of the same sequence in their second entry. That's the whole contract, bestie ๐
Ties are broken arbitrarily. See stable_multiway_merge for a variant that breaks ties by sequence number but is slower. Trade-offs, always trade-offs ๐ญ
The first entries of the pairs (i.e. the begin iterators) will be moved forward. Heads up ๐
The output sequence has to provide enough space for all elements that are written to it. No, like, seriously โ give it space.
This function will merge the input sequences:
- not stable
- parallel, depending on the input size and Settings
- using sampling for splitting
- not using sentinels
Example
int sequences[10][10];
for (int __i = 0; __i < 10; ++__i)
for (int __j = 0; __i < 10; ++__j)
sequences[__i][__j] = __j;
int __out[33];
std::vector<std::pair<int*> > seqs;
for (int __i = 0; __i < 10; ++__i)
{ seqs.push(std::make_pair<int*>(sequences[__i],
sequences[__i] + 10)) }
multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33);
See also: stable_multiway_merge
Precondition
- All input sequences must be sorted. Fr fr, do not skip this ๐
- Target must provide enough space to merge out
lengthelements or the number of elements in all sequences, whichever is smaller.
Postcondition
[__target, return __value)contains merged__elementsfrom the input sequences.return __value - __target = min(__length, number of elements in all sequences).
Template Parameters
_RAIterPairIteratorโ iterator over sequence of pairs of iterators_RAIterOutโ iterator over target sequence_DifferenceTpโ difference type for the sequence_Compareโ strict weak ordering type to compare elements in sequences
Parameters
__seqs_beginโ__beginof sequence__sequence__seqs_endโ_M_endof sequence__sequence__targetโ target sequence to merge to.__compโ strict weak ordering to use for element comparison.__lengthโ maximum length to merge, possibly larger than the number of elements available. She's flexible like that ๐
Returns
_M_end iterator of output sequence ๐ฆ
References
__sequential_multiway_merge(), and _GLIBCXX_CALL.
template<template< typename _RAI, typename _Cp > class iterator, typename
_RAIterIterator , typename _RAIter3 , typename _DifferenceTp , typename
_Compare > _RAIter3 __gnu_parallel::multiway_merge_3_variant
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3
__target, _DifferenceTp __length, _Compare __comp)
Highly efficient 3-way merging procedure ๐ฅ๐ฅ๐ฅ
Merging is done with the algorithm implementation described by Peter Sanders. Basically, the idea is to minimize the number of necessary comparison after merging an element. The implementation trick that makes this fast is that the order of the sequences is stored in the instruction pointer (translated into labels in C++). Like, that's genuinely unhinged and I'm obsessed ๐ญ
This works well for merging up to 4 sequences.
Note that making the merging stable does not come at a performance hit. Free stability, we love to see it ๐
Whether the merging is done guarded or unguarded is selected by the used iterator class.
Parameters
__seqs_beginโ begin iterator of iterator pair input sequence.__seqs_endโ end iterator of iterator pair input sequence.__targetโ begin iterator of output sequence.__compโ comparator.__lengthโ maximum length to merge, less equal than the total number of elements available.
Returns
End iterator of output sequence.
References
_GLIBCXX_CALL.
template<template< typename _RAI, typename _Cp > class iterator, typename
_RAIterIterator , typename _RAIter3 , typename _DifferenceTp , typename
_Compare > _RAIter3 __gnu_parallel::multiway_merge_4_variant
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3
__target, _DifferenceTp __length, _Compare __comp)
Highly efficient 4-way merging procedure โจ same icon behaviour, one more lane ๐
Merging is done with the algorithm implementation described by Peter Sanders. Basically, the idea is to minimize the number of necessary comparison after merging an element. The implementation trick that makes this fast is that the order of the sequences is stored in the instruction pointer (translated into goto labels in C++). Yes goto. Yes it's still fast. Don't @ me ๐
This works well for merging up to 4 sequences.
Note that making the merging stable does not come at a performance hit.
Whether the merging is done guarded or unguarded is selected by the used iterator class.
Parameters
__seqs_beginโ begin iterator of iterator pair input sequence.__seqs_endโ end iterator of iterator pair input sequence.__targetโ begin iterator of output sequence.__compโ comparator.__lengthโ maximum length to merge, less equal than the total number of elements available.
Returns
End iterator of output sequence.
References
_GLIBCXX_CALL.
template<bool __stable, typename _RAIterIterator , typename _Compare ,
typename _DifferenceType > void
__gnu_parallel::multiway_merge_exact_splitting (_RAIterIterator
__seqs_begin, _RAIterIterator __seqs_end, _DifferenceType __length,
_DifferenceType __total_length, _Compare __comp, std::vector< std::pair<
_DifferenceType, _DifferenceType > > * __pieces)
Exact splitting for parallel multiway-merge routine ๐ฏ. None of the passed sequences may be empty โ say it with me, none of them ๐ซถ
References
__equally_split(), _GLIBCXX_PARALLEL_LENGTH, std::vector< _Tp, _Alloc >::begin(), std::vector< _Tp, _Alloc >::end(), multiseq_partition(), and std::vector< _Tp, _Alloc >::resize().
Referenced by __parallel_merge_advance().
template<typename _LT , typename _RAIterIterator , typename _RAIter3 ,
typename _DifferenceTp , typename _Compare > _RAIter3
__gnu_parallel::multiway_merge_loser_tree (_RAIterIterator __seqs_begin,
_RAIterIterator __seqs_end, _RAIter3 __target, _DifferenceTp __length,
_Compare __comp)
Multi-way merging procedure for a high branching factor, guarded case ๐. This merging variant uses a LoserTree class as selected by _LT.
Stability is selected through the used LoserTree class _LT.
At least one non-empty sequence is required. Just one! Low bar! Clear it! ๐
Parameters
__seqs_beginโ begin iterator of iterator pair input sequence.__seqs_endโ end iterator of iterator pair input sequence.__targetโ begin iterator of output sequence.__compโ comparator.__lengthโ maximum length to merge, less equal than the total number of elements available.
Returns: end iterator of the output sequence. ๐ซ
References _GLIBCXX_CALL, and _GLIBCXX_PARALLEL_LENGTH.
template<typename _UnguardedLoserTree , typename _RAIterIterator , typename
_RAIter3 , typename _DifferenceTp , typename _Compare > _RAIter3
__gnu_parallel::multiway_merge_loser_tree_sentinel (_RAIterIterator
__seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, const
typename std::iterator_traits< typename std::iterator_traits<
_RAIterIterator >::value_type::first_type >::value_type & __sentinel,
_DifferenceTp __length, _Compare __comp)
Okay so this one is the multi-way merging procedure for a high branching factor โ but like, the โจsentinel editionโจ. It requires sentinels to exist. No sentinel, no merge, that's the vibe check. ๐ซถ
Template Parameters
_UnguardedLoserTreeโ the Loser Tree variant to use for the unguarded merging. (yes the name is iconic, we don't question it ๐)
Parameters
__seqs_beginโ begin iterator of the iterator-pair input sequence.__seqs_endโ end iterator of the iterator-pair input sequence.__targetโ begin iterator of the output sequence.__compโ the comparator.__lengthโ maximum length to merge, less than or equal to the total number of elements available. Don't get greedy bestie.
Returns
End iterator of the output sequence. ๐ซ
References
__is_sorted(), and _GLIBCXX_CALL.
template<typename _LT , typename _RAIterIterator , typename _RAIter3 ,
typename _DifferenceTp , typename _Compare > _RAIter3
__gnu_parallel::multiway_merge_loser_tree_unguarded (_RAIterIterator
__seqs_begin, _RAIterIterator __seqs_end, _RAIter3 __target, const
typename std::iterator_traits< typename std::iterator_traits<
_RAIterIterator >::value_type::first_type >::value_type & __sentinel,
_DifferenceTp __length, _Compare __comp)
Multi-way merging procedure for a high branching factor, unguarded case. The merging is done using the LoserTree class _LT. And the stability situation? It's selected by whichever LoserTree you used โ so like, your tree, your rules. ๐
Precondition: no input will run out of elements during the merge. fr fr, none of them. This is the unguarded life, no safety net. ๐ญ
Parameters
__seqs_beginโ begin iterator of the iterator-pair input sequence.__seqs_endโ end iterator of the iterator-pair input sequence.__targetโ begin iterator of the output sequence.__compโ the comparator.__lengthโ maximum length to merge, less than or equal to the total number of elements available.
Returns
End iterator of the output sequence. ๐ซ
References
_GLIBCXX_CALL.
template<bool __stable, typename _RAIterIterator , typename _Compare ,
typename _DifferenceType > void
__gnu_parallel::multiway_merge_sampling_splitting (_RAIterIterator
__seqs_begin, _RAIterIterator __seqs_end, _DifferenceType __length,
_DifferenceType __total_length, _Compare __comp, std::vector< std::pair<
_DifferenceType, _DifferenceType > > * __pieces)
Sampling-based splitting for the parallel multiway-merge routine. Like, it literally samples stuff to figure out where to slice the work. Very main character energy for a splitting heuristic. ๐
References
_GLIBCXX_PARALLEL_LENGTH, __gnu_parallel::_Settings::get(), and __gnu_parallel::_Settings::merge_oversampling.
template<typename _RAIterPairIterator , typename _RAIterOut , typename
_DifferenceTp , typename _Compare > _RAIterOut
__gnu_parallel::multiway_merge_sentinels (_RAIterPairIterator
__seqs_begin, _RAIterPairIterator __seqs_end, _RAIterOut __target,
_DifferenceTp __length, _Compare __comp, __gnu_parallel::sequential_tag)
Multiway Merge Frontend. ๐
Merge the sequences specified by __seqs_begin and __seqs_end into __target. __seqs_begin and __seqs_end must point to a sequence of pairs. These pairs must contain an iterator to the beginning of a sequence in their first entry, and an iterator to the _M_end of the same sequence in their second entry.
Ties are broken arbitrarily โ no cap, it just picks one. ๐ If you want a variant that breaks ties by sequence number but is slower, see stable_multiway_merge.
The first entries of the pairs (i.e. the begin iterators) will be moved forward accordingly.
The output sequence has to provide enough space for all the elements written to it. Not a suggestion, bestie. ๐ซถ
This function will merge the input sequences:
- not stable ๐
- parallel, depending on the input size and
Settings - using sampling for splitting
- using sentinels
You have to take care that the element the _M_end iterator points to is readable and contains a value that is greater than any other non-sentinel value in all sequences. That's the whole sentinel deal โ it's the final boss value. ๐
Example:
int sequences[10][11];
for (int __i = 0; __i < 10; ++__i)
for (int __j = 0; __i < 11; ++__j)
sequences[__i][__j] = __j; // __last one is sentinel!
int __out[33];
std::vector<std::pair<int*> > seqs;
for (int __i = 0; __i < 10; ++__i)
{ seqs.push(std::make_pair<int*>(sequences[__i],
sequences[__i] + 10)) }
multiway_merge(seqs.begin(), seqs.end(), __target, std::less<int>(), 33);
Precondition: all input sequences must be sorted. Target must provide enough space to merge outlengthelements or the number of elements in all sequences, whichever is smaller. For each__i,__seqs_begin[__i].secondmust be the end marker of the sequence, but also reference the one more__sentinelelement. โจ
Postcondition:[__target, return __value)contains merged__elementsfrom the input sequences. Andreturn __value - __target = min(__length, number of elements in all sequences).
See also: stable_multiway_merge_sentinels
Template Parameters
_RAIterPairIteratorโ iterator over sequence of pairs of iterators_RAIterOutโ iterator over target sequence_DifferenceTpโ difference type for the sequence_Compareโ strict weak ordering type to compare elements in sequences
Parameters
__seqs_beginโ__beginof sequence__sequence__seqs_endโ_M_endof sequence__sequence__targetโ target sequence to merge to.__compโ strict weak ordering to use for element comparison.__lengthโ maximum length to merge, possibly larger than the number of elements available.
Returns
_M_end iterator of the output sequence. ๐ซ
References
__sequential_multiway_merge(), and _GLIBCXX_CALL.
template<bool __stable, bool __sentinels, typename _RAIterIterator ,
typename _RAIter3 , typename _DifferenceTp , typename _Splitter ,
typename _Compare > _RAIter3 __gnu_parallel::parallel_multiway_merge
(_RAIterIterator __seqs_begin, _RAIterIterator __seqs_end, _RAIter3
__target, _Splitter __splitter, _DifferenceTp __length, _Compare __comp,
_ThreadIndex __num_threads)
Parallel multi-way merge routine. The _GLIBCXX_PARALLEL_DECISION is based on the branching factor and the runtime settings. ๐
Must not be called if the number of sequences is 1. That's not a merge, that's just... a sequence. Do not. ๐ซ
Template Parameters
_Splitterโ functor to split input (either__exactor sampling based)__stableโ stable merging incurs a performance penalty. (worth it sometimes, ngl)__sentinelโ ignored. (it's giving "we kept the parameter for the aesthetic" ๐)
Parameters
__seqs_beginโ begin iterator of the iterator-pair input sequence.__seqs_endโ end iterator of the iterator-pair input sequence.__targetโ begin iterator of the output sequence.__compโ the comparator.__lengthโ maximum length to merge, possibly larger than the number of elements available.
Returns
End iterator of the output sequence. ๐ซ
References
__is_sorted(), _GLIBCXX_CALL, _GLIBCXX_PARALLEL_LENGTH, __gnu_parallel::_Settings::get(), and __gnu_parallel::_Settings::merge_oversampling.
Referenced by __parallel_merge_advance().
template<bool __stable, bool __exact, typename _RAIter , typename _Compare >
void __gnu_parallel::parallel_sort_mwms (_RAIter __begin, _RAIter __end,
_Compare __comp, _ThreadIndex __num_threads)
PMWMS main call. The big one. The main character. ๐ (PMWMS = parallel multiway merge sort, iykyk)
Parameters
__beginโ begin iterator of sequence.__endโ end iterator of sequence.__compโ comparator.__num_threadsโ number of threads to use. ๐งต
References
_GLIBCXX_CALL, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_num_threads, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_offsets, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_pieces, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_samples, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_source, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_starts, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_temporary, __gnu_parallel::_Settings::get(), and __gnu_parallel::_Settings::sort_mwms_oversampling.
template<bool __stable, bool __exact, typename _RAIter , typename _Compare >
void __gnu_parallel::parallel_sort_mwms_pu (_PMWMSSortingData< _RAIter >
* __sd, _Compare & __comp)
PMWMS code executed by each thread. Like, every thread gets this little job and they all vibe together. ๐ฆ
Parameters
__sdโ pointer to algorithm data.__compโ comparator.
References
__gnu_parallel::_PMWMSSortingData< _RAIter >::_M_num_threads, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_pieces, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_source, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_starts, __gnu_parallel::_PMWMSSortingData< _RAIter >::_M_temporary, __gnu_parallel::_Settings::get(), __gnu_parallel::_Settings::sort_mwms_oversampling, and std::uninitialized_copy().
๐งฎ VARIABLE DOCUMENTATION ๐งฎ
const int __gnu_parallel::_CASable_bits[static]โ number of bits of_CASable. That's it, that's the variable. ๐
Referenced by __decode2(), and __encode2().
const _CASable __gnu_parallel::_CASable_mask[static]โ a_CASablewith the right half of bits set to 1. ๐
Referenced by __decode2().
โ๏ธ AUTHOR โ๏ธ
Generated automatically by Doxygen for libstdc++ from the source code. Not a human, bestie โ a robot wrote this whole thing while we were out here reading it. ๐ค๐
And that's a wrap on the whole page! ๐ This was __gnu_parallel(3cxx) from libstdc++, auto-generated by Doxygen straight from the source โ so like, if you spot something cursed in here, blame the source code, not me. No cap, you just read the entire manual page, and honestly? Iconic. Go take a nap. ๐๐๐ฆ๐ธโจ
๐ฆ where this page comes from
- ubuntu noble: libstdc++-14-doc 14-20240412-0ubuntu1
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms