• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #868

16 Jan 2023 08:21PM UTC coverage: 86.487%. Remained the same
#868

push

StellarBot
Merge #6137

6137: Adding example of a simple master/slave distributed application r=hkaiser a=hkaiser

The purpose of this example is to demonstrate how HPX actions can be used to build a simple master-slave application. The master (locality 0) assigns work to the slaves (all other localities). Note that if this application is run on one locality only it uses the same locality for the master and the slave functionalities.

The slaves receive a message that encodes how many sub-tasks of a certain type they should spawn locally.


Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

72 of 72 new or added lines in 1 file covered. (100.0%)

174663 of 201952 relevant lines covered (86.49%)

1849169.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.41
/libs/core/algorithms/include/hpx/parallel/algorithms/partial_sort.hpp
1
//  Copyright (c) 2020 Francisco Jose Tapia
2
//  Copyright (c) 2021 Akhil J Nair
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
/// \file parallel/algorithms/partial_sort.hpp
9

10
#pragma once
11

12
#if defined(DOXYGEN)
13
namespace hpx {
14
    // clang-format off
15

16
    ///////////////////////////////////////////////////////////////////////////
17
    /// Places the first middle - first elements from the range [first, last)
18
    /// as sorted with respect to comp into the range [first, middle). The rest
19
    /// of the elements in the range [middle, last) are placed in an unspecified
20
    /// order.
21
    ///
22
    /// \note   Complexity: Approximately (last - first) * log(middle - first)
23
    ///         comparisons.
24
    ///
25
    /// \tparam RandIter    The type of the source begin, middle, and end
26
    ///                     iterators used (deduced). This iterator type must
27
    ///                     meet the requirements of a random access iterator.
28
    /// \tparam Comp        The type of the function/function object to use
29
    ///                     (deduced). Comp defaults to detail::less.
30
    ///
31
    /// \param first        Refers to the beginning of the sequence of elements
32
    ///                     the algorithm will be applied to.
33
    /// \param middle       Refers to the middle of the sequence of elements
34
    ///                     the algorithm will be applied to.
35
    /// \param last         Refers to the end of the sequence of elements the
36
    ///                     algorithm will be applied to.
37
    /// \param comp         comp is a callable object. The return value of the
38
    ///                     INVOKE operation applied to an object of type Comp,
39
    ///                     when contextually converted to bool, yields true if
40
    ///                     the first argument of the call is less than the
41
    ///                     second, and false otherwise. It is assumed that
42
    ///                     comp will not apply any non-constant function
43
    ///                     through the dereferenced iterator. It defaults to
44
    ///                     detail::less.
45
    ///
46
    /// \returns  The \a partial_sort algorithm returns a \a RandIter
47
    ///           that refers to \a last.
48
    ///
49
    template <typename RandIter, typename Comp = hpx::parallel::v1::detail::less>
50
    RandIter partial_sort(RandIter first, RandIter middle, RandIter last,
51
        Comp&& comp = Comp());
52

53
    ///////////////////////////////////////////////////////////////////////////
54
    /// Places the first middle - first elements from the range [first, last)
55
    /// as sorted with respect to comp into the range [first, middle). The rest
56
    /// of the elements in the range [middle, last) are placed in an unspecified
57
    /// order.
58
    ///
59
    /// \note   Complexity: Approximately (last - first) * log(middle - first)
60
    ///         comparisons.
61
    ///
62
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
63
    ///                     It describes the manner in which the execution
64
    ///                     of the algorithm may be parallelized and the manner
65
    ///                     in which it applies user-provided function objects.
66
    /// \tparam RandIter    The type of the source begin, middle, and end
67
    ///                     iterators used (deduced). This iterator type must
68
    ///                     meet the requirements of a random access iterator.
69
    /// \tparam Comp        The type of the function/function object to use
70
    ///                     (deduced). Comp defaults to detail::less.
71
    ///
72
    /// \param policy       The execution policy to use for the scheduling of
73
    ///                     the iterations.
74
    /// \param first        Refers to the beginning of the sequence of elements
75
    ///                     the algorithm will be applied to.
76
    /// \param middle       Refers to the middle of the sequence of elements
77
    ///                     the algorithm will be applied to.
78
    /// \param last         Refers to the end of the sequence of elements the
79
    ///                     algorithm will be applied to.
80
    /// \param comp         comp is a callable object. The return value of the
81
    ///                     INVOKE operation applied to an object of type Comp,
82
    ///                     when contextually converted to bool, yields true if
83
    ///                     the first argument of the call is less than the
84
    ///                     second, and false otherwise. It is assumed that
85
    ///                     comp will not apply any non-constant function
86
    ///                     through the dereferenced iterator. It defaults to
87
    ///                     detail::less.
88
    ///
89
    /// \returns  The \a partial_sort algorithm returns a
90
    ///           \a hpx::future<RandIter> if the execution policy is of
91
    ///           type \a sequenced_task_policy or
92
    ///           \a parallel_task_policy and returns \a RandIter otherwise.
93
    ///           The iterator returned refers to \a last.
94
    ///
95
    template <typename ExPolicy, typename RandIter,
96
        typename Comp = hpx::parallel::v1::detail::less>
97
    parallel::util::detail::algorithm_result_t<ExPolicy, RandIter> partial_sort(
98
        ExPolicy&& policy, RandIter first, RandIter middle, RandIter last,
99
        Comp&& comp = Comp());
100

101
    // clang-format on
102
}    // namespace hpx
103

104
#else
105

106
#include <hpx/config.hpp>
107
#include <hpx/assert.hpp>
108
#include <hpx/async_local/dataflow.hpp>
109
#include <hpx/concepts/concepts.hpp>
110
#include <hpx/functional/invoke.hpp>
111
#include <hpx/iterator_support/traits/is_iterator.hpp>
112
#include <hpx/parallel/util/detail/sender_util.hpp>
113
#include <hpx/type_support/decay.hpp>
114

115
#include <hpx/algorithms/traits/projected.hpp>
116
#include <hpx/execution/algorithms/detail/predicates.hpp>
117
#include <hpx/execution/executors/execution.hpp>
118
#include <hpx/execution/executors/execution_information.hpp>
119
#include <hpx/execution/executors/execution_parameters.hpp>
120
#include <hpx/executors/exception_list.hpp>
121
#include <hpx/executors/execution_policy.hpp>
122
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
123
#include <hpx/parallel/algorithms/detail/distance.hpp>
124
#include <hpx/parallel/algorithms/detail/is_sorted.hpp>
125
#include <hpx/parallel/algorithms/sort.hpp>
126
#include <hpx/parallel/util/compare_projected.hpp>
127
#include <hpx/parallel/util/detail/algorithm_result.hpp>
128
#include <hpx/parallel/util/detail/chunk_size.hpp>
129
#include <hpx/parallel/util/projection_identity.hpp>
130

131
#include <algorithm>
132
#include <cstddef>
133
#include <cstdint>
134
#include <exception>
135
#include <functional>
136
#include <iterator>
137
#include <list>
138
#include <type_traits>
139
#include <utility>
140

141
namespace hpx { namespace parallel { inline namespace v1 {
142

143
    ///////////////////////////////////////////////////////////////////////////
144
    // sort
145
    namespace detail {
146

147
        /// \cond NOINTERNAL
148

149
        //////////////////////////////////////////////////////////////////////
150
        ///
151
        /// \brief Obtain the position of the most significant bit set in N
152
        ///
153
        /// \param num : Number to examine
154
        ///
155
        /// \return Position of the first bit set
156
        ///
157
        inline constexpr unsigned nbits64(std::uint64_t num) noexcept
49,469✔
158
        {
159
            unsigned nb = 0;
49,469✔
160
            if (num >= (1ull << 32))
49,469✔
161
            {
162
                nb += 32;
×
163
                num = (num >> 32);
×
164
            }
×
165
            if (num >= (1ull << 16))
49,469✔
166
            {
167
                nb += 16;
22✔
168
                num = (num >> 16);
22✔
169
            }
22✔
170
            if (num >= (1ull << 8))
49,469✔
171
            {
172
                nb += 8;
46,329✔
173
                num = (num >> 8);
46,329✔
174
            }
46,329✔
175
            if (num >= (1ull << 4))
49,469✔
176
            {
177
                nb += 4;
13,239✔
178
                num = (num >> 4);
13,239✔
179
            }
13,239✔
180
            if (num >= (1ull << 2))
49,469✔
181
            {
182
                nb += 2;
3,138✔
183
                num = (num >> 2);
3,138✔
184
            }
3,138✔
185
            if (num >= (1ull << 1))
49,469✔
186
            {
187
                nb += 1;
46,361✔
188
                num = (num >> 1);
46,361✔
189
            }
46,361✔
190
            return nb;
49,469✔
191
        }
192

193
        ///////////////////////////////////////////////////////////////////////
194
        ///
195
        /// Receive a range between first and last, obtain 9 values
196
        /// between the elements  including the first and the previous
197
        /// to the last. Obtain the iterator to the mid value and swap
198
        /// with the first position
199
        //
200
        /// \param first    iterator to the first element
201
        /// \param last     iterator to the last element
202
        /// \param comp     object to Comp two elements
203
        ///
204
        template <typename Iter, typename Comp>
205
        inline constexpr void pivot3(
352,261✔
206
            Iter first, Iter last, Comp&& comp) noexcept
207
        {
208
            auto N2 = (last - first) >> 1;
352,261✔
209
            Iter it_val =
210
                mid3(first + 1, first + N2, last - 1, HPX_FORWARD(Comp, comp));
352,261✔
211
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
212
            std::ranges::iter_swap(first, it_val);
213
#else
214
            std::iter_swap(first, it_val);
352,261✔
215
#endif
216
        }
352,261✔
217

218
        ///////////////////////////////////////////////////////////////////////
219
        ///
220
        /// This function obtain a pivot in the range and filter the elements
221
        /// according the value of that pivot
222
        ///
223
        /// \param first : iterator to the first element
224
        /// \param end : iterator to the element after the last
225
        /// \param comp : object to Comp two elements
226
        ///
227
        /// \return iterator where is the pivot used in the filtering
228
        ///
229
        template <typename Iter, typename Comp>
230
        constexpr inline Iter filter(Iter first, Iter end, Comp&& comp)
369,641✔
231
        {
232
            std::int64_t nelem = (end - first);
369,641✔
233
            if (nelem > 4096)
369,641✔
234
            {
235
                pivot9(first, end, comp);
17,380✔
236
            }
17,376✔
237
            else
238
            {
239
                pivot3(first, end, comp);
352,261✔
240
            }
241

242
            typename std::iterator_traits<Iter>::value_type const& pivot =
369,637✔
243
                *first;
369,637✔
244

245
            Iter c_first = first + 1, c_last = end - 1;
369,637✔
246
            while (HPX_INVOKE(comp, *c_first, pivot))
978,084✔
247
            {
248
                ++c_first;
608,447✔
249
            }
250
            while (HPX_INVOKE(comp, pivot, *c_last))
946,432✔
251
            {
252
                --c_last;
576,795✔
253
            }
254

255
            while (c_first < c_last)
163,726,126✔
256
            {
257
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
258
                std::ranges::iter_swap(c_first++, c_last--);
259
#else
260
                std::iter_swap(c_first++, c_last--);
163,356,489✔
261
#endif
262
                while (HPX_INVOKE(comp, *c_first, pivot))
480,171,624✔
263
                {
264
                    ++c_first;
316,815,135✔
265
                }
266
                while (HPX_INVOKE(comp, pivot, *c_last))
332,733,770✔
267
                {
268
                    --c_last;
169,377,281✔
269
                }
270
            }
271

272
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
273
            std::ranges::iter_swap(first, c_last);
274
#else
275
            std::iter_swap(first, c_last);
369,637✔
276
#endif
277
            return c_last;
369,637✔
278
        }
4✔
279

280
        ///////////////////////////////////////////////////////////////////////
281
        ///
282
        /// Internal function to divide and sort the ranges
283
        //
284
        /// \param first : iterator to the first element to be sorted
285
        /// \param middle: iterator defining the last element to be sorted
286
        /// \param end : iterator to the element after the end in the range
287
        /// \param level : level of depth from the top level call
288
        /// \param comp : object for to Comp elements
289
        ///
290
        template <typename Iter, typename Comp>
291
        inline void recursive_partial_sort(
299,928✔
292
            Iter first, Iter middle, Iter end, std::uint32_t level, Comp&& comp)
293
        {
294
            constexpr std::uint32_t nmin = 24;
299,928✔
295
            std::int64_t nelem = end - first;
299,928✔
296
            std::int64_t nmid = middle - first;
299,928✔
297
            if (nelem == 0 || nmid == 0)
299,928✔
298
            {
299
                return;
2,656✔
300
            }
301

302
            if (nelem < nmin)
297,272✔
303
            {
304
                std::sort(first, end, comp);
32,742✔
305
                return;
32,742✔
306
            }
307

308
            if (nmid == 1)
264,530✔
309
            {
310
                for (Iter it = first + 1; it != end; ++it)
155,176✔
311
                {
312
                    if (HPX_INVOKE(comp, *it, *first))
153,817✔
313
                    {
314
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
315
                        std::ranges::iter_swap(it, first);
316
#else
317
                        std::iter_swap(it, first);
5,092✔
318
#endif
319
                    }
5,092✔
320
                }
153,817✔
321
                return;
1,359✔
322
            }
323

324
            if (level == 0)
263,171✔
325
            {
326
                std::make_heap(first, end, comp);
×
327
                std::sort_heap(first, middle, comp);
×
328
                return;
×
329
            }
330

331
            Iter c_last = filter(first, end, comp);
263,171✔
332
            if (middle >= c_last)
263,171✔
333
            {
334
                std::sort(first, c_last, comp);
137,019✔
335
                if (middle != c_last)
137,019✔
336
                {
337
                    recursive_partial_sort(c_last + 1, middle, end, level - 1,
268,682✔
338
                        HPX_FORWARD(Comp, comp));
134,341✔
339
                }
134,341✔
340
                return;
137,019✔
341
            }
342

343
            recursive_partial_sort(
126,152✔
344
                first, middle, c_last, level - 1, HPX_FORWARD(Comp, comp));
126,152✔
345
        }
299,928✔
346

347
        ///////////////////////////////////////////////////////////////////////
348
        ///
349
        /// Internal function to divide and sort the ranges
350
        ///
351
        /// \param first : iterator to the first element
352
        /// \param middle: iterator defining the last element to be sorted
353
        /// \param end : iterator to the element after the end in the range
354
        /// \param level : level of depth from the top level call
355
        /// \param comp : object for to Comp elements
356
        ///
357
        struct sort_thread_helper
358
        {
359
            template <typename... Ts>
360
            decltype(auto) operator()(Ts&&... ts) const
82✔
361
            {
362
                return sort_thread(HPX_FORWARD(Ts, ts)...);
82✔
363
            }
364
        };
365

366
        template <typename ExPolicy, typename Iter, typename Comp>
367
        hpx::future<Iter> parallel_partial_sort(ExPolicy&& policy, Iter first,
368
            Iter middle, Iter last, std::uint32_t level, Comp&& comp = Comp());
369

370
        struct parallel_partial_sort_helper
371
        {
372
            template <typename... Ts>
373
            decltype(auto) operator()(Ts&&... ts) const
82✔
374
            {
375
                return parallel_partial_sort(HPX_FORWARD(Ts, ts)...);
82✔
376
            }
377
        };
378

379
        template <typename ExPolicy, typename Iter, typename Comp>
380
        hpx::future<Iter> parallel_partial_sort(ExPolicy&& policy, Iter first,
19,851✔
381
            Iter middle, Iter last, std::uint32_t level, Comp&& comp)
382
        {
383
            std::int64_t nelem = last - first;
19,851✔
384
            std::int64_t nmid = middle - first;
19,851✔
385
            HPX_ASSERT(nelem >= nmid);
19,851✔
386

387
            if (nelem == 0 || nmid == 0)
19,851✔
388
            {
389
                return hpx::make_ready_future(last);
2✔
390
            }
391

392
            if (nmid < 4096 || level < 12)
19,849✔
393
            {
394
                recursive_partial_sort(first, middle, last, level, comp);
19,767✔
395
                return hpx::make_ready_future(last);
19,767✔
396
            }
397

398
            Iter c_last = filter(first, last, comp);
82✔
399
            if (middle >= c_last)
82✔
400
            {
401
                // figure out the chunk size to use
402
                std::size_t const cores =
82✔
403
                    execution::processing_units_count(policy.parameters(),
164✔
404
                        policy.executor(), hpx::chrono::null_duration, nelem);
82✔
405

406
                // number of elements to sort
407
                std::size_t chunk_size = execution::get_chunk_size(
82✔
408
                    policy.parameters(), policy.executor(),
82✔
409
                    hpx::chrono::null_duration, cores, nelem);
410

411
                hpx::future<Iter> left = execution::async_execute(
82✔
412
                    policy.executor(), sort_thread_helper(), policy, first,
82✔
413
                    c_last, comp, chunk_size);
82✔
414

415
                hpx::future<Iter> right;
82✔
416
                if (middle != c_last)
82✔
417
                {
418
                    right = execution::async_execute(policy.executor(),
164✔
419
                        parallel_partial_sort_helper(), policy, c_last + 1,
82✔
420
                        middle, last, level - 1, comp);
82✔
421
                }
82✔
422
                else
423
                {
424
                    right = hpx::make_ready_future(last);
×
425
                }
426

427
                return hpx::dataflow(
82✔
428
                    [last](hpx::future<Iter>&& left,
164✔
429
                        hpx::future<Iter>&& right) -> Iter {
430
                        if (left.has_exception() || right.has_exception())
82✔
431
                        {
432
                            std::list<std::exception_ptr> errors;
×
433
                            if (left.has_exception())
×
434
                                errors.push_back(left.get_exception_ptr());
×
435
                            if (right.has_exception())
×
436
                                errors.push_back(right.get_exception_ptr());
×
437

438
                            throw exception_list(HPX_MOVE(errors));
×
439
                        }
×
440
                        return last;
82✔
441
                    },
×
442
                    HPX_MOVE(left), HPX_MOVE(right));
443
            }
82✔
444

445
            return parallel_partial_sort(HPX_FORWARD(ExPolicy, policy), first,
×
446
                middle, c_last, level - 1, HPX_FORWARD(Comp, comp));
×
447
        }
19,851✔
448
        /// \endcond NOINTERNAL
449
    }    // end namespace detail
450

451
    ///////////////////////////////////////////////////////////////////////////
452
    ///
453
    /// \brief : Rearranges elements such that the range [first, middle)
454
    ///          contains the sorted middle - first smallest elements in the
455
    ///          range [first, end).
456
    ///
457
    /// \param first : iterator to the first element
458
    /// \param middle: iterator defining the last element to be sorted
459
    /// \param end : iterator to the element after the end in the range
460
    /// \param comp : object for to Comp elements
461
    ///
462
    template <typename Iter, typename Sent, typename Comp>
463
    Iter sequential_partial_sort(Iter first, Iter middle, Sent end, Comp&& comp)
19,668✔
464
    {
465
        std::int64_t nelem = parallel::v1::detail::distance(first, end);
19,668✔
466
        HPX_ASSERT(nelem >= 0);
19,668✔
467

468
        std::int64_t nmid = middle - first;
19,668✔
469
        HPX_ASSERT(nmid >= 0 && nmid <= nelem);
19,668✔
470

471
        if (nmid > 1024)
19,668✔
472
        {
473
            if (detail::is_sorted_sequential(first, middle, comp))
1✔
474
            {
475
                return first + nelem;
×
476
            }
477
        }
1✔
478

479
        std::uint32_t level = detail::nbits64(nelem) * 2;
19,668✔
480
        detail::recursive_partial_sort(
19,668✔
481
            first, middle, first + nelem, level, HPX_FORWARD(Comp, comp));
19,668✔
482
        return first + nelem;
19,668✔
483
    }
19,668✔
484

485
    ///////////////////////////////////////////////////////////////////////////
486
    ///
487
    /// \brief : Rearranges elements such that the range [first, middle)
488
    ///          contains the sorted middle - first smallest elements in the
489
    ///          range [first, end).
490
    ///
491
    /// \param first : iterator to the first element
492
    /// \param middle: iterator defining the last element to be sorted
493
    /// \param end : iterator to the element after the end in the range
494
    /// \param comp : object for to Comp elements
495
    ///
496
    template <typename ExPolicy, typename Iter, typename Sent, typename Comp>
497
    hpx::future<Iter> parallel_partial_sort(
19,769✔
498
        ExPolicy&& policy, Iter first, Iter middle, Sent end, Comp&& comp)
499
    {
500
        std::int64_t nelem = parallel::v1::detail::distance(first, end);
19,769✔
501
        HPX_ASSERT(nelem >= 0);
19,769✔
502

503
        std::int64_t nmid = middle - first;
19,769✔
504
        HPX_ASSERT(nmid >= 0 && nmid <= nelem);
19,769✔
505

506
        if (nmid > 1024)
19,769✔
507
        {
508
            if (detail::is_sorted_sequential(first, middle, comp))
91✔
509
            {
510
                return hpx::make_ready_future(first + nelem);
×
511
            }
512
        }
91✔
513

514
        std::uint32_t level = parallel::v1::detail::nbits64(nelem) * 2;
19,769✔
515
        return detail::parallel_partial_sort(HPX_FORWARD(ExPolicy, policy),
39,538✔
516
            first, middle, first + nelem, level, HPX_FORWARD(Comp, comp));
19,769✔
517
    }
19,769✔
518

519
    ///////////////////////////////////////////////////////////////////////
520
    // partial_sort
521
    template <typename RandIter>
522
    struct partial_sort
523
      : public detail::algorithm<partial_sort<RandIter>, RandIter>
524
    {
525
        partial_sort()
39,437✔
526
          : partial_sort::algorithm("partial_sort")
39,437✔
527
        {
39,437✔
528
        }
39,437✔
529

530
        template <typename ExPolicy, typename Iter, typename Sent,
531
            typename Comp, typename Proj>
532
        static Iter sequential(ExPolicy, Iter first, Iter middle, Sent last,
19,668✔
533
            Comp&& comp, Proj&& proj)
534
        {
535
            return sequential_partial_sort(first, middle, last,
39,336✔
536
                util::compare_projected<Comp&, Proj&>(comp, proj));
19,668✔
537
        }
538

539
        template <typename ExPolicy, typename Iter, typename Sent,
540
            typename Comp, typename Proj>
541
        static typename util::detail::algorithm_result<ExPolicy, Iter>::type
542
        parallel(ExPolicy&& policy, Iter first, Iter middle, Sent last,
19,769✔
543
            Comp&& comp, Proj&& proj)
544
        {
545
            typedef util::detail::algorithm_result<ExPolicy, Iter>
546
                algorithm_result;
547

548
            try
549
            {
550
                // call the sort routine and return the right type,
551
                // depending on execution policy
552
                return algorithm_result::get(parallel_partial_sort(
19,769✔
553
                    HPX_FORWARD(ExPolicy, policy), first, middle, last,
19,769✔
554
                    util::compare_projected<Comp&, Proj&>(comp, proj)));
19,769✔
555
            }
×
556
            catch (...)
557
            {
558
                return algorithm_result::get(
×
559
                    detail::handle_exception<ExPolicy, Iter>::call(
×
560
                        std::current_exception()));
×
561
            }
×
562
        }
19,769✔
563
    };
564
}}}    // namespace hpx::parallel::v1
565

566
namespace hpx {
567

568
    inline constexpr struct partial_sort_t final
569
      : hpx::detail::tag_parallel_algorithm<partial_sort_t>
570
    {
571
    private:
572
        // clang-format off
573
        template <typename RandIter,
574
            typename Comp = hpx::parallel::v1::detail::less,
575
            HPX_CONCEPT_REQUIRES_(
576
                hpx::traits::is_iterator<RandIter>::value &&
577
                hpx::is_invocable_v<Comp,
578
                    typename std::iterator_traits<RandIter>::value_type,
579
                    typename std::iterator_traits<RandIter>::value_type
580
                >
581
            )>
582
        // clang-format on
583
        friend RandIter tag_fallback_invoke(hpx::partial_sort_t, RandIter first,
2,114✔
584
            RandIter middle, RandIter last, Comp&& comp = Comp())
585
        {
586
            static_assert(
587
                hpx::traits::is_random_access_iterator<RandIter>::value,
588
                "Requires at least random access iterator.");
589

590
            return parallel::v1::partial_sort<RandIter>().call(
4,228✔
591
                hpx::execution::seq, first, middle, last,
592
                HPX_FORWARD(Comp, comp), parallel::util::projection_identity());
2,114✔
593
        }
594

595
        // clang-format off
596
        template <typename ExPolicy, typename RandIter,
597
            typename Comp = hpx::parallel::v1::detail::less,
598
            HPX_CONCEPT_REQUIRES_(
599
                hpx::is_execution_policy<ExPolicy>::value &&
600
                hpx::traits::is_iterator<RandIter>::value &&
601
                hpx::is_invocable_v<Comp,
602
                    typename std::iterator_traits<RandIter>::value_type,
603
                    typename std::iterator_traits<RandIter>::value_type
604
                >
605
            )>
606
        // clang-format on
607
        friend typename parallel::util::detail::algorithm_result<ExPolicy,
608
            RandIter>::type
609
        tag_fallback_invoke(hpx::partial_sort_t, ExPolicy&& policy,
10,263✔
610
            RandIter first, RandIter middle, RandIter last,
611
            Comp&& comp = Comp())
612
        {
613
            static_assert(
614
                hpx::traits::is_random_access_iterator<RandIter>::value,
615
                "Requires at least random access iterator.");
616

617
            using algorithm_result =
618
                parallel::util::detail::algorithm_result<ExPolicy, RandIter>;
619

620
            return algorithm_result::get(
10,263✔
621
                parallel::v1::partial_sort<RandIter>().call(
20,526✔
622
                    HPX_FORWARD(ExPolicy, policy), first, middle, last,
10,263✔
623
                    HPX_FORWARD(Comp, comp),
10,263✔
624
                    parallel::util::projection_identity()));
625
        }
×
626
    } partial_sort{};
627
}    // namespace hpx
628

629
#endif    // DOXYGEN
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc