CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
Partitioner.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
15
16#include <algorithm>
17#include <cstddef>
18#include <thread>
19
25
26namespace CeresEngine {
27
38 std::size_t mMinimumGrainSize;
39
40 public:
43 constexpr explicit HalvePartitioner(const std::size_t minimumGrainSize) : mMinimumGrainSize(minimumGrainSize) {}
44
51 template<typename I, typename S> auto operator()(I first, S last) {
52 const std::size_t size = std::distance(first, last);
53 return (size <= mMinimumGrainSize) ? last : std::next(first, (size + 1) / 2);
54 }
55 };
56
64 std::size_t mMinimumGrainSize;
66
67 public:
70
71 template<typename I, typename S> auto operator()(I first, S last) {
72 if(mThreadCount <= 1) {
73 return last;
74 }
75
76 mThreadCount = (mThreadCount + 1) / 2;
77 const std::size_t size = std::distance(first, last);
78 return (size <= mMinimumGrainSize) ? last : std::next(first, (size + 1) / 2);
79 }
80 };
81
86
89 constexpr std::size_t make_grain_size(const std::size_t n, const std::size_t occupancy = hardware_concurrency()) {
90 return std::clamp(n / (8 * std::max(occupancy, static_cast<std::size_t>(1))), size_t(1), size_t(2048));
91 }
92
100
105 template<traits::input_iterator I, traits::sentinel_for<I> S>
107 return make_default_partitioner(std::distance(first, last), occupancy);
108 }
109
114 template<traits::input_range R> DefaultPartitioner make_default_partitioner(R&& r, std::size_t occupancy = hardware_concurrency()) {
115 return make_default_partitioner(std::begin(r), std::end(r), occupancy);
116 }
117
121 template<traits::executor E> DefaultPartitioner make_default_partitioner(const E& executor, const size_t n) {
122 if constexpr(can_query<E, ExecutorOccupancy>::value) {
123 const size_t occupancy = query(executor, ExecutorOccupancy{});
125 }
127 }
128
133 template<traits::executor E, traits::input_iterator I, traits::sentinel_for<I> S>
134 DefaultPartitioner make_default_partitioner(const E& executor, I first, S last) {
135 return make_default_partitioner(executor, std::distance(first, last));
136 }
137
142 template<traits::executor E, traits::input_range R> DefaultPartitioner make_default_partitioner(const E& executor, R&& r) {
143 return make_default_partitioner(executor, std::begin(r), std::end(r));
144 }
145
146 namespace traits {
148 template<class T, class I, class S>
149 using is_partitioner = std::conjunction<std::conditional_t<traits::is_input_iterator_v<I>, std::true_type, std::false_type>,
150 std::conditional_t<traits::is_input_iterator_v<S>, std::true_type, std::false_type>, std::is_invocable<T, I, S>>;
151
153 template<class T, class I, class S> constexpr bool is_partitioner_v = is_partitioner<T, I, S>::value;
154
156 template<class T, class I, class S>
158
160 template<class T, class R> struct is_range_partitioner : std::false_type {};
161 template<class T, traits::range R> struct is_range_partitioner<T, R> : is_partitioner<T, traits::iterator_t<R>, traits::iterator_t<R>> {};
162
164 template<class T, class R> constexpr bool is_range_partitioner_v = is_range_partitioner<T, R>::value;
165
167 template<class T, class R>
169 } // namespace traits
170
171} // namespace CeresEngine
The halve partitioner always splits the sequence into two parts of roughly equal size.
Definition Partitioner.hpp:37
auto operator()(I first, S last)
Split a range of elements.
Definition Partitioner.hpp:51
constexpr HalvePartitioner(const std::size_t minimumGrainSize)
Halve partition constructor.
Definition Partitioner.hpp:43
std::size_t mMinimumGrainSize
Definition Partitioner.hpp:38
A partitioner that splits the ranges until it identifies we are not moving to new threads.
Definition Partitioner.hpp:63
ThreadPartitioner(const std::size_t minimumGrainSize, const std::size_t occupancy=hardware_concurrency())
Definition Partitioner.hpp:68
std::size_t mThreadCount
Definition Partitioner.hpp:65
auto operator()(I first, S last)
Definition Partitioner.hpp:71
std::size_t mMinimumGrainSize
Definition Partitioner.hpp:64
Definition Partitioner.hpp:157
Definition Partitioner.hpp:168
std::conjunction< std::conditional_t< traits::is_input_iterator_v< I >, std::true_type, std::false_type >, std::conditional_t< traits::is_input_iterator_v< S >, std::true_type, std::false_type >, std::is_invocable< T, I, S > > is_partitioner
Determine if P is a valid partitioner for the iterator range [I,S].
Definition Partitioner.hpp:150
constexpr bool is_partitioner_v
Determine if P is a valid partitioner for the iterator range [I,S].
Definition Partitioner.hpp:153
constexpr bool is_range_partitioner_v
Determine if P is a valid partitioner for the range R.
Definition Partitioner.hpp:164
Definition Application.hpp:19
constexpr std::size_t make_grain_size(const std::size_t n, const std::size_t occupancy=hardware_concurrency())
Determine a reasonable minimum grain size depending on the number of elements in a sequence.
Definition Partitioner.hpp:89
constexpr std::size_t hardware_concurrency() noexcept
A version of hardware_concurrency that always returns at least 1.
Definition ExecutionContext.hpp:597
asio::execution::occupancy_t ExecutorOccupancy
Definition ExecutionContext.hpp:212
ThreadPartitioner DefaultPartitioner
Default partitioner used by parallel algorithms.
Definition Partitioner.hpp:85
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
DefaultPartitioner make_default_partitioner(const size_t n, const std::size_t occupancy=hardware_concurrency())
Create an instance of the default partitioner with a reasonable grain size for n elements.
Definition Partitioner.hpp:97
Determine if P is a valid partitioner for the range R.
Definition Partitioner.hpp:160