17 #ifndef STXXL_PARALLEL_MULTIWAY_MERGE_HEADER
18 #define STXXL_PARALLEL_MULTIWAY_MERGE_HEADER
35 #if defined(_MSC_VER) && STXXL_DEBUG_ASSERTIONS
37 typedef SSIZE_T ssize_t;
45 template <
typename RandomAccessIteratorPair>
46 typename std::iterator_traits<
47 typename RandomAccessIteratorPair::first_type
51 return p.second - p.first;
59 template <
typename RandomAccessIterator,
typename Comparator>
67 typedef typename std::iterator_traits<RandomAccessIterator>::value_type
value_type;
73 RandomAccessIterator
end;
87 : current(begin), end(end), comp(comp)
130 return bi1.
comp(*bi1, *bi2);
145 return !bi1.
comp(*bi2, *bi1);
149 template <
typename RandomAccessIterator,
typename Comparator>
157 typedef typename std::iterator_traits<RandomAccessIterator>::value_type
value_type;
173 RandomAccessIterator ,
175 : current(begin), comp(comp)
214 return bi1.
comp(*bi1, *bi2);
225 return !bi1.
comp(*bi2, *bi1);
239 template <
bool Stable,
typename RandomAccessIteratorIterator,
typename Comparator>
240 typename std::iterator_traits<
241 typename std::iterator_traits<RandomAccessIteratorIterator>::value_type::first_type
244 RandomAccessIteratorIterator seqs_end,
250 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
251 ::value_type::first_type RandomAccessIterator;
252 typedef typename std::iterator_traits<RandomAccessIterator>
253 ::value_type value_type;
254 typedef typename std::iterator_traits<RandomAccessIterator>
255 ::difference_type diff_type;
257 if ((*seqs_begin).first == (*seqs_begin).second)
265 value_type
min = *((*seqs_begin).second - 1);
267 for (RandomAccessIteratorIterator s = seqs_begin + 1; s != seqs_end; ++s)
269 if ((*s).first == (*s).second)
272 min_sequence =
static_cast<int>(s - seqs_begin);
275 const value_type& v = *((*s).second - 1);
280 min_sequence =
static_cast<int>(s - seqs_begin);
284 diff_type overhang_size = 0;
287 for (s = 0; s <= min_sequence; ++s)
289 RandomAccessIterator
split;
291 split = std::upper_bound(seqs_begin[s].first, seqs_begin[s].second,
294 split = std::lower_bound(seqs_begin[s].first, seqs_begin[s].second,
297 overhang_size += seqs_begin[s].second -
split;
300 for ( ; s < (seqs_end - seqs_begin); ++s)
302 RandomAccessIterator
split =
303 std::lower_bound(seqs_begin[s].first, seqs_begin[s].second,
305 overhang_size += seqs_begin[s].second -
split;
308 return overhang_size;
317 template <
typename RandomAccessIteratorIterator,
typename Comparator>
318 typename std::iterator_traits<
319 typename std::iterator_traits<RandomAccessIteratorIterator>::value_type::first_type
322 RandomAccessIteratorIterator seqs_end,
327 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
328 ::value_type::first_type RandomAccessIterator;
329 typedef typename std::iterator_traits<RandomAccessIterator>
330 ::value_type value_type;
331 typedef typename std::iterator_traits<RandomAccessIterator>
332 ::difference_type diff_type;
334 value_type* max_value = NULL;
335 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
337 if ((*s).first == (*s).second)
339 value_type& v = *((*s).second - 1);
340 if (!max_value || comp(*max_value, v))
344 diff_type overhang_size = 0;
346 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
348 RandomAccessIterator
split = std::lower_bound((*s).first, (*s).second, *max_value, comp);
349 overhang_size += (*s).second -
split;
350 *((*s).second) = *max_value;
353 return overhang_size;
379 template <
template <
typename RAI,
typename C>
class Iterator,
380 typename RandomAccessIteratorIterator,
381 typename RandomAccessIterator3,
382 typename DiffType,
typename Comparator>
383 RandomAccessIterator3
385 RandomAccessIteratorIterator seqs_end,
386 RandomAccessIterator3 target, DiffType length,
392 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
393 ::value_type::first_type RandomAccessIterator;
398 #if STXXL_DEBUG_ASSERTIONS
399 ssize_t orig_length = length;
402 Iterator<RandomAccessIterator, Comparator>
403 seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
404 seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
405 seq2(seqs_begin[2].first, seqs_begin[2].second, comp);
411 else if (seq2 < seq0)
429 #define STXXL_MERGE3CASE(a, b, c, c0, c1) \
431 *target = *seq ## a; \
435 if (length == 0) goto finish; \
436 if (seq ## a c0 seq ## b) goto s ## a ## b ## c; \
437 if (seq ## a c1 seq ## c) goto s ## b ## a ## c; \
438 goto s ## b ## c ## a;
447 #undef STXXL_MERGE3CASE
452 #if STXXL_DEBUG_ASSERTIONS
454 (seq1.iterator() - seqs_begin[1].first) +
455 (seq2.iterator() - seqs_begin[2].first),
459 seqs_begin[0].first = seq0.iterator();
460 seqs_begin[1].first = seq1.iterator();
461 seqs_begin[2].first = seq2.iterator();
466 template <
typename RandomAccessIteratorIterator,
467 typename RandomAccessIterator3,
468 typename DiffType,
typename Comparator>
469 RandomAccessIterator3
471 RandomAccessIteratorIterator seqs_end,
472 RandomAccessIterator3 target, DiffType length,
479 RandomAccessIterator3 target_end;
480 DiffType overhang = prepare_unguarded<true>(seqs_begin, seqs_end, comp, min_seq);
482 DiffType total_length = 0;
483 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
486 if (overhang != (DiffType)(-1))
488 DiffType unguarded_length =
std::min(length, total_length - overhang);
489 target_end = multiway_merge_3_variant<unguarded_iterator>
490 (seqs_begin, seqs_end, target, unguarded_length, comp);
491 overhang = length - unguarded_length;
508 seqs_begin[1].first, seqs_begin[1].second,
509 seqs_begin[2].first, seqs_begin[2].second,
510 target_end, overhang, comp);
514 seqs_begin[0].first, seqs_begin[0].second,
515 seqs_begin[2].first, seqs_begin[2].second,
516 target_end, overhang, comp);
520 seqs_begin[0].first, seqs_begin[0].second,
521 seqs_begin[1].first, seqs_begin[1].second,
522 target_end, overhang, comp);
557 template <
template <
typename RAI,
typename C>
class iterator,
558 typename RandomAccessIteratorIterator,
559 typename RandomAccessIterator3,
560 typename DiffType,
typename Comparator>
561 RandomAccessIterator3
563 RandomAccessIteratorIterator seqs_end,
564 RandomAccessIterator3 target, DiffType length,
570 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
571 ::value_type::first_type RandomAccessIterator;
576 #if STXXL_DEBUG_ASSERTIONS
577 ssize_t orig_length = length;
580 iterator<RandomAccessIterator, Comparator>
581 seq0(seqs_begin[0].first, seqs_begin[0].second, comp),
582 seq1(seqs_begin[1].first, seqs_begin[1].second, comp),
583 seq2(seqs_begin[2].first, seqs_begin[2].second, comp),
584 seq3(seqs_begin[3].first, seqs_begin[3].second, comp);
586 #define STXXL_DECISION(a, b, c, d) do { \
587 if (seq ## d < seq ## a) goto s ## d ## a ## b ## c; \
588 if (seq ## d < seq ## b) goto s ## a ## d ## b ## c; \
589 if (seq ## d < seq ## c) goto s ## a ## b ## d ## c; \
590 goto s ## a ## b ## c ## d; \
598 else if (seq2 < seq0)
616 #define STXXL_MERGE4CASE(a, b, c, d, c0, c1, c2) \
617 s ## a ## b ## c ## d: \
618 if (length == 0) goto finish; \
619 *target = *seq ## a; \
623 if (seq ## a c0 seq ## b) goto s ## a ## b ## c ## d; \
624 if (seq ## a c1 seq ## c) goto s ## b ## a ## c ## d; \
625 if (seq ## a c2 seq ## d) goto s ## b ## c ## a ## d; \
626 goto s ## b ## c ## d ## a;
653 #undef STXXL_MERGE4CASE
654 #undef STXXL_DECISION
659 #if STXXL_DEBUG_ASSERTIONS
661 (seq1.iterator() - seqs_begin[1].first) +
662 (seq2.iterator() - seqs_begin[2].first) +
663 (seq3.iterator() - seqs_begin[3].first),
667 seqs_begin[0].first = seq0.iterator();
668 seqs_begin[1].first = seq1.iterator();
669 seqs_begin[2].first = seq2.iterator();
670 seqs_begin[3].first = seq3.iterator();
675 template <
typename RandomAccessIteratorIterator,
676 typename RandomAccessIterator3,
677 typename DiffType,
typename Comparator>
678 RandomAccessIterator3
680 RandomAccessIteratorIterator seqs_end,
681 RandomAccessIterator3 target, DiffType length,
687 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
688 ::value_type RandomAccessIteratorPair;
691 RandomAccessIterator3 target_end;
692 DiffType overhang = prepare_unguarded<true>(seqs_begin, seqs_end, comp, min_seq);
694 DiffType total_length = 0;
695 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
698 if (overhang != (DiffType) - 1)
700 DiffType unguarded_length =
std::min(length, total_length - overhang);
701 target_end = multiway_merge_4_variant<unguarded_iterator>
702 (seqs_begin, seqs_end, target, unguarded_length, comp);
703 overhang = length - unguarded_length;
715 std::vector<RandomAccessIteratorPair> one_missing(seqs_begin, seqs_end);
716 one_missing.erase(one_missing.begin() + min_seq);
718 target_end = multiway_merge_3_variant<guarded_iterator>(one_missing.begin(), one_missing.end(), target_end, overhang, comp);
720 one_missing.insert(one_missing.begin() + min_seq, seqs_begin[min_seq]);
721 std::copy(one_missing.begin(), one_missing.end(), seqs_begin);
743 template <
bool Stable,
744 typename RandomAccessIteratorIterator,
745 typename RandomAccessIterator3,
746 typename DiffType,
typename Comparator>
747 RandomAccessIterator3
749 RandomAccessIteratorIterator seqs_end,
750 RandomAccessIterator3 target, DiffType length,
755 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
756 ::value_type::first_type RandomAccessIterator;
757 typedef typename std::iterator_traits<RandomAccessIterator>
758 ::value_type value_type;
761 int k =
static_cast<int>(seqs_end - seqs_begin), nrp;
763 value_type* pl =
new value_type[k];
764 int* source =
new int[k];
765 DiffType total_length = 0;
767 #define POS(i) seqs_begin[(i)].first
768 #define STOPS(i) seqs_begin[(i)].second
772 for (
int pi = 0; pi < k; ++pi)
776 pl[nrp] = *(
POS(pi));
785 for (
int k = 0; k < nrp - 1; ++k)
786 for (
int pi = nrp - 1; pi > k; --pi)
787 if (comp(pl[pi], pl[pi - 1]) ||
788 (!comp(pl[pi - 1], pl[pi]) && source[pi] < source[pi - 1]))
790 std::swap(pl[pi - 1], pl[pi]);
791 std::swap(source[pi - 1], source[pi]);
796 for (
int k = 0; k < nrp - 1; ++k)
797 for (
int pi = nrp - 1; pi > k; --pi)
798 if (comp(pl[pi], pl[pi - 1]))
800 std::swap(pl[pi - 1], pl[pi]);
801 std::swap(source[pi - 1], source[pi]);
809 while (nrp > 0 && length > 0)
811 if (source[0] < source[1])
814 while ((nrp == 1 || !(comp(pl[1], pl[0]))) && length > 0)
820 if (
POS(source[0]) ==
STOPS(source[0]))
823 for (
int s = 0; s < nrp - 1; ++s)
826 source[s] = source[s + 1];
832 pl[0] = *(
POS(source[0]));
838 while ((nrp == 1 || comp(pl[0], pl[1])) && length > 0)
844 if (
POS(source[0]) ==
STOPS(source[0]))
846 for (
int s = 0; s < nrp - 1; ++s)
849 source[s] = source[s + 1];
855 pl[0] = *(
POS(source[0]));
861 while ((j < nrp) && (comp(pl[j], pl[j - 1]) ||
862 (!comp(pl[j - 1], pl[j]) && (source[j] < source[j - 1]))))
864 std::swap(pl[j - 1], pl[j]);
865 std::swap(source[j - 1], source[j]);
873 while (nrp > 0 && length > 0)
876 while ((nrp == 1 || !comp(pl[1], pl[0])) && length > 0)
882 if (
POS(source[0]) ==
STOPS(source[0]))
884 for (
int s = 0; s < (nrp - 1); ++s)
887 source[s] = source[s + 1];
893 pl[0] = *(
POS(source[0]));
898 while ((j < nrp) && comp(pl[j], pl[j - 1]))
900 std::swap(pl[j - 1], pl[j]);
901 std::swap(source[j - 1], source[j]);
925 template <
typename LoserTreeType,
926 typename RandomAccessIteratorIterator,
927 typename RandomAccessIterator3,
928 typename DiffType,
typename Comparator>
929 RandomAccessIterator3
931 RandomAccessIteratorIterator seqs_end,
932 RandomAccessIterator3 target, DiffType length,
937 typedef typename LoserTreeType::source_type source_type;
938 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
939 ::value_type::first_type RandomAccessIterator;
940 typedef typename std::iterator_traits<RandomAccessIterator>
941 ::value_type value_type;
943 source_type k =
static_cast<source_type
>(seqs_end - seqs_begin);
945 LoserTreeType lt(k, comp);
947 DiffType total_length = 0;
949 const value_type* arbitrary_element = NULL;
952 for (source_type t = 0; t < k; ++t)
955 arbitrary_element = &(*seqs_begin[t].first);
960 for (source_type t = 0; t < k; ++t)
962 if (
UNLIKELY(seqs_begin[t].first == seqs_begin[t].second))
963 lt.insert_start(*arbitrary_element, t,
true);
965 lt.insert_start(*seqs_begin[t].first, t,
false);
970 total_length =
std::min(total_length, length);
972 for (DiffType i = 0; i < total_length; ++i)
975 source_type source = lt.get_min_source();
977 *target = *seqs_begin[source].first;
979 ++seqs_begin[source].first;
982 if (seqs_begin[source].first == seqs_begin[source].second)
983 lt.delete_min_insert(*arbitrary_element,
true);
986 lt.delete_min_insert(*seqs_begin[source].first,
false);
1005 template <
typename LoserTreeType,
1006 typename RandomAccessIteratorIterator,
1007 typename RandomAccessIterator3,
1009 typename Comparator>
1010 RandomAccessIterator3
1012 RandomAccessIteratorIterator seqs_begin,
1013 RandomAccessIteratorIterator seqs_end,
1014 RandomAccessIterator3 target, DiffType length,
1019 int k = (int)(seqs_end - seqs_begin);
1022 LoserTreeType lt(k, *(seqs_begin->second - 1), comp);
1024 DiffType total_length = 0;
1026 for (
int t = 0; t < k; ++t)
1028 assert(seqs_begin[t].first != seqs_begin[t].second);
1030 lt.insert_start(*seqs_begin[t].first, t);
1038 length =
std::min(total_length, length);
1042 #if STXXL_DEBUG_ASSERTIONS
1046 RandomAccessIterator3 target_end = target + length;
1047 while (target < target_end)
1050 source = lt.get_min_source();
1052 #if STXXL_DEBUG_ASSERTIONS
1053 assert(i == 0 || !comp(*(seqs_begin[source].first), *(target - 1)));
1056 *target = *seqs_begin[source].first;
1057 ++seqs_begin[source].first;
1060 #if STXXL_DEBUG_ASSERTIONS
1061 assert((seqs_begin[source].first != seqs_begin[source].second) || (i == length - 1));
1066 lt.delete_min_insert(*seqs_begin[source].first);
1072 template <
bool Stable,
class ValueType,
class Comparator>
1079 #define STXXL_NO_POINTER(T) \
1080 template <bool Stable, class Comparator> \
1081 struct loser_tree_traits<Stable, T, Comparator> \
1083 typedef LoserTreeCopy<Stable, T, Comparator> LT; \
1097 #undef STXXL_NO_POINTER
1099 template <
bool Stable,
class ValueType,
class Comparator>
1106 #define STXXL_NO_POINTER_UNGUARDED(T) \
1107 template <bool Stable, class Comparator> \
1108 struct loser_tree_traits_unguarded<Stable, T, Comparator> \
1110 typedef LoserTreeCopyUnguarded<Stable, T, Comparator> LT; \
1124 #undef STXXL_NO_POINTER_UNGUARDED
1126 template <
bool Stable,
1127 typename RandomAccessIteratorIterator,
1128 typename RandomAccessIterator3,
1129 typename DiffType,
typename Comparator>
1130 RandomAccessIterator3
1132 RandomAccessIteratorIterator seqs_begin,
1133 RandomAccessIteratorIterator seqs_end,
1134 RandomAccessIterator3 target, DiffType length,
1139 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1140 ::value_type::first_type RandomAccessIterator;
1141 typedef typename std::iterator_traits<RandomAccessIterator>
1142 ::value_type value_type;
1145 RandomAccessIterator3 target_end;
1146 DiffType overhang = prepare_unguarded<Stable>(seqs_begin, seqs_end, comp, min_seq);
1148 DiffType total_length = 0;
1149 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
1152 if (overhang != (DiffType)(-1))
1154 DiffType unguarded_length =
std::min(length, total_length - overhang);
1157 (seqs_begin, seqs_end, target, unguarded_length, comp);
1158 overhang = length - unguarded_length;
1164 target_end = target;
1172 (seqs_begin, seqs_end, target_end, overhang, comp);
1180 template <
bool Stable,
1181 typename RandomAccessIteratorIterator,
1182 typename RandomAccessIterator3,
1183 typename DiffType,
typename Comparator>
1184 RandomAccessIterator3
1186 RandomAccessIteratorIterator seqs_begin,
1187 RandomAccessIteratorIterator seqs_end,
1188 RandomAccessIterator3 target, DiffType length,
1193 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1194 ::value_type::first_type RandomAccessIterator;
1195 typedef typename std::iterator_traits<RandomAccessIterator>
1196 ::value_type value_type;
1199 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
1202 RandomAccessIterator3 target_end
1205 (seqs_begin, seqs_end, target, length, comp);
1211 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
1231 template <
bool Stable,
bool Sentinels,
1232 typename RandomAccessIteratorIterator,
1233 typename RandomAccessIterator3,
1234 typename DiffType,
typename Comparator>
1235 RandomAccessIterator3
1237 RandomAccessIteratorIterator seqs_end,
1238 RandomAccessIterator3 target, DiffType length,
1243 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1244 ::value_type::first_type RandomAccessIterator;
1245 typedef typename std::iterator_traits<RandomAccessIterator>
1246 ::value_type value_type;
1248 for (RandomAccessIteratorIterator s = seqs_begin; s != seqs_end; ++s)
1251 RandomAccessIterator3 return_target = target;
1252 int k =
static_cast<int>(seqs_end - seqs_begin);
1256 if (!Sentinels && mwma == SETTINGS::LOSER_TREE_SENTINEL)
1257 mwma = SETTINGS::LOSER_TREE_COMBINED;
1264 return_target = std::copy(seqs_begin[0].first,
1265 seqs_begin[0].first + length,
1267 seqs_begin[0].first += length;
1271 seqs_begin[0].first, seqs_begin[0].second,
1272 seqs_begin[1].first, seqs_begin[1].second,
1273 target, length, comp);
1278 case SETTINGS::LOSER_TREE_COMBINED:
1280 seqs_begin, seqs_end, target, length, comp);
1282 case SETTINGS::LOSER_TREE_SENTINEL:
1283 return_target = multiway_merge_3_variant<unguarded_iterator>(
1284 seqs_begin, seqs_end, target, length, comp);
1287 return_target = multiway_merge_3_variant<guarded_iterator>(
1288 seqs_begin, seqs_end, target, length, comp);
1295 case SETTINGS::LOSER_TREE_COMBINED:
1297 seqs_begin, seqs_end, target, length, comp);
1299 case SETTINGS::LOSER_TREE_SENTINEL:
1300 return_target = multiway_merge_4_variant<unguarded_iterator>(
1301 seqs_begin, seqs_end, target, length, comp);
1304 return_target = multiway_merge_4_variant<guarded_iterator>(
1305 seqs_begin, seqs_end, target, length, comp);
1313 case SETTINGS::BUBBLE:
1314 return_target = multiway_merge_bubble<Stable>(
1315 seqs_begin, seqs_end, target, length, comp);
1317 case SETTINGS::LOSER_TREE:
1320 seqs_begin, seqs_end, target, length, comp);
1322 case SETTINGS::LOSER_TREE_COMBINED:
1323 return_target = multiway_merge_loser_tree_combined<Stable>(
1324 seqs_begin, seqs_end, target, length, comp);
1326 case SETTINGS::LOSER_TREE_SENTINEL:
1327 return_target = multiway_merge_loser_tree_sentinel<Stable>(
1328 seqs_begin, seqs_end, target, length, comp);
1331 assert(0 &&
"multiway_merge algorithm not implemented");
1339 return return_target;
1356 template <
bool Stable,
1357 typename RandomAccessIteratorIterator,
1359 typename Comparator>
1362 const RandomAccessIteratorIterator& seqs_begin,
1363 const RandomAccessIteratorIterator& seqs_end,
1364 DiffType length, DiffType total_length, Comparator comp,
1365 std::vector<
typename std::iterator_traits<RandomAccessIteratorIterator>::value_type>* chunks,
1368 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1369 ::value_type::first_type RandomAccessIterator;
1370 typedef typename std::iterator_traits<RandomAccessIterator>
1371 ::value_type value_type;
1373 const DiffType num_seqs = seqs_end - seqs_begin;
1374 const DiffType num_samples = num_threads * SETTINGS::merge_oversampling;
1377 value_type* samples =
new value_type[num_seqs * num_samples];
1379 for (DiffType s = 0; s < num_seqs; ++s)
1381 for (DiffType i = 0; i < num_samples; ++i)
1383 DiffType sample_index =
static_cast<DiffType
>(
1385 * (double(i + 1) / double(num_samples + 1))
1386 * (
double(length) / double(total_length))
1388 samples[s * num_samples + i] = seqs_begin[s].first[sample_index];
1393 std::stable_sort(samples, samples + (num_samples * num_seqs), comp);
1395 std::sort(samples, samples + (num_samples * num_seqs), comp);
1401 for (DiffType seq = 0; seq < num_seqs; ++seq)
1404 chunks[slab][seq].first =
1406 seqs_begin[seq].first, seqs_begin[seq].second,
1407 samples[num_samples * num_seqs * slab / num_threads],
1411 chunks[slab][seq].first = seqs_begin[seq].first;
1413 if ((slab + 1) < num_threads) {
1414 chunks[slab][seq].second =
1416 seqs_begin[seq].first, seqs_begin[seq].second,
1417 samples[num_samples * num_seqs * (slab + 1) / num_threads],
1421 chunks[slab][seq].second = seqs_begin[seq].second;
1442 template <
bool Stable,
1443 typename RandomAccessIteratorIterator,
1445 typename Comparator>
1448 const RandomAccessIteratorIterator& seqs_begin,
1449 const RandomAccessIteratorIterator& seqs_end,
1450 DiffType length, DiffType total_length, Comparator comp,
1451 std::vector<
typename std::iterator_traits<RandomAccessIteratorIterator>::value_type>* chunks,
1454 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1455 ::value_type RandomAccessIteratorPair;
1456 typedef typename RandomAccessIteratorPair
1457 ::first_type RandomAccessIterator;
1459 const size_t num_seqs = seqs_end - seqs_begin;
1460 const bool tight = (total_length == length);
1462 std::vector<RandomAccessIterator>* offsets
1463 =
new std::vector<RandomAccessIterator>[num_threads];
1465 std::vector<DiffType> ranks(num_threads + 1);
1470 offsets[s].resize(num_seqs);
1472 ranks[s + 1], offsets[s].begin(), comp);
1476 offsets[num_threads - 1].resize(num_seqs);
1478 length, offsets[num_threads - 1].begin(), comp);
1486 for (
size_t s = 0; s < num_seqs; ++s)
1489 chunks[slab][s].first = seqs_begin[s].first;
1491 chunks[slab][s].first = offsets[slab - 1][s];
1493 if (!tight || slab < (num_threads - 1))
1494 chunks[slab][s].second = offsets[slab][s];
1496 chunks[slab][s].second = seqs_begin[s].second;
1518 template <
bool Stable,
1519 typename RandomAccessIteratorIterator,
1520 typename RandomAccessIterator3,
1522 typename Comparator>
1523 RandomAccessIterator3
1524 parallel_multiway_merge(RandomAccessIteratorIterator seqs_begin,
1525 RandomAccessIteratorIterator seqs_end,
1526 RandomAccessIterator3 target,
const DiffType length,
1531 typedef typename std::iterator_traits<RandomAccessIteratorIterator>
1532 ::value_type RandomAccessIteratorPair;
1534 for (RandomAccessIteratorIterator rii = seqs_begin; rii != seqs_end; ++rii)
1538 std::vector<RandomAccessIteratorPair> seqs_ne;
1539 seqs_ne.reserve(seqs_end - seqs_begin);
1540 DiffType total_length = 0;
1542 for (RandomAccessIteratorIterator raii = seqs_begin; raii != seqs_end; ++raii)
1546 total_length += length;
1547 seqs_ne.push_back(*raii);
1551 size_t num_seqs = seqs_ne.size();
1555 if (total_length == 0 || num_seqs == 0)
1559 std::min(static_cast<DiffType>(SETTINGS::num_threads), total_length));
1561 Timing<inactive_tag>* t =
new Timing<inactive_tag>[num_threads];
1563 for (
int pr = 0; pr < num_threads; ++pr)
1568 std::vector<RandomAccessIteratorPair>* chunks
1569 =
new std::vector<RandomAccessIteratorPair>[num_threads];
1571 for (
int s = 0; s < num_threads; ++s)
1572 chunks[s].resize(num_seqs);
1574 #pragma omp parallel num_threads(num_threads)
1578 if (SETTINGS::multiway_merge_splitting == SETTINGS::SAMPLING)
1580 parallel_multiway_merge_sampling_splitting<Stable>(
1581 seqs_ne.begin(), seqs_ne.end(),
1582 length, total_length, comp,
1583 chunks, num_threads);
1587 parallel_multiway_merge_exact_splitting<Stable>(
1588 seqs_ne.begin(), seqs_ne.end(),
1589 length, total_length, comp,
1590 chunks, num_threads);
1597 DiffType target_position = 0, local_length = 0;
1599 for (
size_t s = 0; s < num_seqs; ++s)
1601 target_position += chunks[iam][s].first - seqs_ne[s].first;
1605 sequential_multiway_merge<Stable, false>(
1606 chunks[iam].begin(), chunks[iam].end(),
1607 target + target_position,
1608 std::min(local_length, length - target_position),
1614 for (
int pr = 0; pr < num_threads; ++pr)
1620 size_t count_seqs = 0;
1621 for (RandomAccessIteratorIterator raii = seqs_begin; raii != seqs_end; ++raii)
1625 raii->first = chunks[num_threads - 1][count_seqs++].second;
1631 for (
int pr = 0; pr < num_threads; ++pr)
1633 for (
int pr = 0; pr < num_threads; ++pr)
1637 return target + length;
1650 template <
typename RandomAccessIteratorPairIterator,
1651 typename RandomAccessIterator3,
1652 typename DiffType,
typename Comparator>
1653 RandomAccessIterator3
1655 RandomAccessIteratorPairIterator seqs_end,
1656 RandomAccessIterator3 target, DiffType length,
1661 if (seqs_begin == seqs_end)
1664 RandomAccessIterator3 target_end;
1666 ((seqs_end - seqs_begin) >= SETTINGS::multiway_merge_minimal_k) &&
1669 target_end = parallel_multiway_merge<false>(
1670 seqs_begin, seqs_end, target, length, comp);
1672 target_end = sequential_multiway_merge<false, false>(
1673 seqs_begin, seqs_end, target, length, comp);
1688 template <
typename RandomAccessIteratorPairIterator,
1689 typename RandomAccessIterator3,
1690 typename DiffType,
typename Comparator>
1691 RandomAccessIterator3
1693 RandomAccessIteratorPairIterator seqs_end,
1694 RandomAccessIterator3 target, DiffType length,
1699 if (seqs_begin == seqs_end)
1702 RandomAccessIterator3 target_end;
1704 ((seqs_end - seqs_begin) >= SETTINGS::multiway_merge_minimal_k) &&
1707 target_end = parallel_multiway_merge<true>(
1708 seqs_begin, seqs_end, target, length, comp);
1710 target_end = sequential_multiway_merge<true, false>(
1711 seqs_begin, seqs_end, target, length, comp);
1731 template <
typename RandomAccessIteratorPairIterator,
1732 typename RandomAccessIterator3,
1733 typename DiffType,
typename Comparator>
1734 RandomAccessIterator3
1736 RandomAccessIteratorPairIterator seqs_end,
1737 RandomAccessIterator3 target, DiffType length,
1740 if (seqs_begin == seqs_end)
1746 ((seqs_end - seqs_begin) >= SETTINGS::multiway_merge_minimal_k) &&
1749 return parallel_multiway_merge<false>(
1750 seqs_begin, seqs_end, target, length, comp);
1752 return sequential_multiway_merge<false, true>(
1753 seqs_begin, seqs_end, target, length, comp);
1771 template <
typename RandomAccessIteratorPairIterator,
1772 typename RandomAccessIterator3,
1773 typename DiffType,
typename Comparator>
1774 RandomAccessIterator3
1776 RandomAccessIteratorPairIterator seqs_end,
1777 RandomAccessIterator3 target, DiffType length,
1780 if (seqs_begin == seqs_end)
1786 ((seqs_end - seqs_begin) >= SETTINGS::multiway_merge_minimal_k) &&
1789 return parallel_multiway_merge<true>(
1790 seqs_begin, seqs_end, target, length, comp);
1792 return sequential_multiway_merge<true, true>(
1793 seqs_begin, seqs_end, target, length, comp);
1796 #endif // STXXL_PARALLEL
1802 #endif // !STXXL_PARALLEL_MULTIWAY_MERGE_HEADER
#define STXXL_ASSERT(condition)
RandomAccessIterator3 multiway_merge_4_combined(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
RandomAccessIterator3 multiway_merge_stable_sentinels(RandomAccessIteratorPairIterator seqs_begin, RandomAccessIteratorPairIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Multi-way merging front-end.
void multiseq_partition(const RanSeqs &begin_seqs, const RanSeqs &end_seqs, const RankType &rank, RankIterator begin_offsets, Comparator 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 seq...
RandomAccessIterator3 multiway_merge_loser_tree_sentinel(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
unguarded_iterator< RandomAccessIterator, Comparator > self_type
Our own type.
RandomAccessIterator3 multiway_merge_loser_tree_combined(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
void sort(ExtIterator first, ExtIterator last, StrictWeakOrdering cmp, unsigned_type M)
Sort records comparison-based, see stxxl::sort -- Sorting Comparison-Based.
std::iterator_traits< RandomAccessIterator >::value_type value_type
Value type of the iterator.
Comparator & comp
Comparator.
Comparator & comp
Comparator.
LoserTreePointerUnguarded< Stable, ValueType, Comparator > LT
guarded_iterator< RandomAccessIterator, Comparator > self_type
Our own type.
guarded_iterator(RandomAccessIterator begin, RandomAccessIterator end, Comparator &comp)
Constructor.
RandomAccessIterator3 multiway_merge(RandomAccessIteratorPairIterator seqs_begin, RandomAccessIteratorPairIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Multi-way merging dispatcher.
static uint_pair min()
return an uint_pair instance containing the smallest value possible
uint_pair & operator++()
prefix increment operator (directly manipulates the integer parts)
#define STXXL_DEBUG_ASSERT(condition)
RandomAccessIterator end
End iterator of the sequence.
#define STXXL_CHECK_EQUAL(a, b)
STXXL_CHECK_EQUAL(a,b) is an assertion macro for unit tests, similar to STXXL_CHECK(a==b). The difference is that STXXL_CHECK_EQUAL(a,b) also prints the values of a and b. Attention: a and b must be printable with std::cout!
void parallel_multiway_merge_exact_splitting(const RandomAccessIteratorIterator &seqs_begin, const RandomAccessIteratorIterator &seqs_end, DiffType length, DiffType total_length, Comparator comp, std::vector< typename std::iterator_traits< RandomAccessIteratorIterator >::value_type > *chunks, const thread_index_t num_threads)
Splitting method for parallel multi-way merge routine: use multisequence selection for exact splittin...
DiffTypeOutputIterator equally_split(DiffType n, thread_index_t p, DiffTypeOutputIterator s)
Split a sequence into parts of almost equal size.
void parallel_multiway_merge_sampling_splitting(const RandomAccessIteratorIterator &seqs_begin, const RandomAccessIteratorIterator &seqs_end, DiffType length, DiffType total_length, Comparator comp, std::vector< typename std::iterator_traits< RandomAccessIteratorIterator >::value_type > *chunks, const thread_index_t num_threads)
Splitting method for parallel multi-way merge routine: use sampling and binary search for in-exact sp...
RandomAccessIterator3 sequential_multiway_merge(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Sequential multi-way merging switch.
RandomAccessIterator3 multiway_merge_loser_tree_unguarded(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Multi-way merging procedure for a high branching factor, unguarded case.
#define STXXL_PARALLEL_CONDITION(c)
RandomAccessIterator3 multiway_merge_sentinels(RandomAccessIteratorPairIterator seqs_begin, RandomAccessIteratorPairIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Multi-way merging front-end.
bool operator<=(const uint_pair &b) const
less-or-equal comparison operator
#define STXXL_MERGE3CASE(a, b, c, c0, c1)
static std::vector< std::string > split(const std::string &str, const std::string &sep, unsigned int min_fields=0, unsigned int limit_fields=std::numeric_limits< unsigned int >::max())
Split a string by given separator string. Returns a vector of strings with at least min_fields and at...
RandomAccessIterator3 multiway_merge_stable(RandomAccessIteratorPairIterator seqs_begin, RandomAccessIteratorPairIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Multi-way merging dispatcher.
RandomAccessIterator3 multiway_merge_loser_tree(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Multi-way merging procedure for a high branching factor, guarded case.
OutputIterator merge_advance(RandomAccessIterator1 &begin1, RandomAccessIterator1 end1, RandomAccessIterator2 &begin2, RandomAccessIterator2 end2, OutputIterator target, DiffType max_length, Comparator comp)
Merge routine being able to merge only the max_length smallest elements.
bool operator<(const uint_pair &b) const
less-than comparison operator
RandomAccessIterator & iterator()
Convert to wrapped iterator.
#define STXXL_BEGIN_NAMESPACE
#define STXXL_MERGE4CASE(a, b, c, d, c0, c1, c2)
bool is_sorted(ForwardIterator first, ForwardIterator last, StrictWeakOrdering comp)
std::iterator_traits< typename std::iterator_traits< RandomAccessIteratorIterator >::value_type::first_type >::difference_type prepare_unguarded_sentinel(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, Comparator comp)
Prepare a set of sequences to be merged with a (end) guard (sentinel)
#define STXXL_NO_POINTER_UNGUARDED(T)
RandomAccessIterator3 multiway_merge_4_variant(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Highly efficient 4-way merging procedure.
#define STXXL_PARALLEL_PCALL(n)
RandomAccessIterator3 multiway_merge_3_variant(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Highly efficient 3-way merging procedure.
RandomAccessIterator current
Current iterator position.
RandomAccessIterator3 multiway_merge_bubble(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
Basic multi-way merging procedure.
RandomAccessIterator & iterator()
Convert to wrapped iterator.
std::iterator_traits< RandomAccessIterator >::value_type value_type
Value type of the iterator.
Iterator wrapper supporting an implicit supremum at the end of the sequence, dominating all compariso...
LoserTreePointer< Stable, ValueType, Comparator > LT
#define STXXL_DECISION(a, b, c, d)
std::iterator_traits< typename std::iterator_traits< RandomAccessIteratorIterator >::value_type::first_type >::difference_type prepare_unguarded(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, Comparator comp, int &min_sequence)
Prepare a set of sequences to be merged without a (end) guard.
RandomAccessIterator3 multiway_merge_3_combined(RandomAccessIteratorIterator seqs_begin, RandomAccessIteratorIterator seqs_end, RandomAccessIterator3 target, DiffType length, Comparator comp)
unguarded_iterator(RandomAccessIterator begin, RandomAccessIterator, Comparator &comp)
Constructor.
RandomAccessIterator current
Current iterator position.
#define STXXL_NO_POINTER(T)
#define STXXL_END_NAMESPACE
std::iterator_traits< typename RandomAccessIteratorPair::first_type >::difference_type iterpair_size(const RandomAccessIteratorPair &p)
Length of a sequence described by a pair of iterators.