15 #ifndef PAAL_SCHEDULING_JOBS_HPP
16 #define PAAL_SCHEDULING_JOBS_HPP
18 #define BOOST_RESULT_OF_USE_DECLTYPE
26 #include <boost/range/algorithm/copy.hpp>
27 #include <boost/range/algorithm/sort.hpp>
28 #include <boost/range/counting_range.hpp>
29 #include <boost/range/iterator_range.hpp>
30 #include <boost/range/numeric.hpp>
45 template <
class MachineIterator,
class JobIterator,
class GetSpeed,
48 typedef typename std::iterator_traits<MachineIterator>::reference
50 typedef typename std::iterator_traits<JobIterator>::reference job_reference;
56 template <
class MachineIterator,
class JobIterator,
class GetSpeed,
58 MachineIterator, JobIterator, GetSpeed, GetLoad>>
59 typename Traits::frac_t calculate_bound(
const MachineIterator mfirst,
60 const MachineIterator mlast,
61 const JobIterator jfirst,
62 const JobIterator jlast,
63 GetSpeed get_speed, GetLoad get_load) {
64 typedef typename Traits::speed_t Speed;
65 typedef typename Traits::load_t Load;
66 typedef typename Traits::frac_t
Frac;
68 auto jobs_num = jlast - jfirst;
69 auto machines_num = mlast - mfirst;
71 std::vector<Speed> speed_sum(machines_num);
72 std::transform(mfirst, mlast, speed_sum.begin(), get_speed);
73 boost::partial_sum(speed_sum, speed_sum.begin());
75 std::vector<Load> load_sum(jobs_num);
76 std::transform(jfirst, jlast, load_sum.begin(), get_load);
77 boost::partial_sum(load_sum, load_sum.begin());
79 typedef decltype(machines_num) MachinesNumType;
80 assert(jobs_num > 0 && machines_num > 0);
81 Frac result(get_load(*jfirst), get_speed(*mfirst));
82 for (auto jobID :
irange(jobs_num)) {
83 Load load = get_load(jfirst[jobID]);
84 auto get_single = [ = ](MachinesNumType i) {
85 return Frac(load, get_speed(mfirst[i]));
87 auto get_summed = [&](MachinesNumType i) {
88 return Frac(load_sum[jobID], speed_sum[i]);
90 auto condition = [ = ](MachinesNumType i) {
91 return get_summed(i) >= get_single(i);
93 auto machines_ids = boost::counting_range(
94 static_cast<MachinesNumType>(0), machines_num);
98 auto it = std::partition_point(machines_ids.begin(), machines_ids.end(),
100 MachinesNumType machineID =
101 (it != machines_ids.end()) ? *it : machines_num - 1;
102 auto getMax = [ = ](MachinesNumType i) {
103 return std::max(get_single(i), get_summed(i));
106 Frac candidate = getMax(machineID);
107 if (machineID != 0) {
115 template <
class MachineIterator,
class JobIterator,
class OutputIterator,
116 class GetSpeed,
class GetLoad,
class RoundFun>
117 void schedule(MachineIterator mfirst, MachineIterator mlast, JobIterator jfirst,
118 JobIterator jlast, OutputIterator result, GetSpeed get_speed,
119 GetLoad get_load, RoundFun round) {
120 typedef sched_traits<MachineIterator, JobIterator, GetSpeed, GetLoad>
122 typedef typename Traits::speed_t Speed;
123 typedef typename Traits::load_t Load;
125 if (mfirst == mlast || jfirst == jlast) {
129 std::vector<MachineIterator> machines;
130 boost::copy(boost::counting_range(mfirst, mlast),
131 std::back_inserter(machines));
136 std::vector<JobIterator> jobs;
137 boost::copy(boost::counting_range(jfirst, jlast), std::back_inserter(jobs));
142 auto bound = detail::calculate_bound(
143 machines.begin(), machines.end(), jobs.begin(), jobs.end(),
144 get_speed_from_iterator, get_load_from_iterator);
145 Load bound_load = bound.num;
146 Speed bound_speed = bound.den;
148 auto emit = [&result](MachineIterator miter, JobIterator jiter) {
149 *result = std::make_pair(miter, jiter);
152 auto job_iter = jobs.begin();
153 for (
auto machine_iter = machines.begin(); machine_iter != machines.end();
155 auto &&machine = *(*machine_iter);
156 Speed speed = get_speed(machine);
157 while (job_iter != jobs.end()) {
158 auto &&job = *(*job_iter);
159 Load job_load = get_load(job) * bound_speed,
160 new_load = current_load + job_load;
161 assert(new_load <= bound_load * (2 * speed));
162 if (bound_load * speed < new_load) {
163 Load frac_load = bound_load * speed - current_load;
164 if (round(frac_load, job_load)) {
165 emit(*machine_iter, *job_iter);
167 auto next_machine_iter = std::next(machine_iter);
168 assert(next_machine_iter != machines.end());
169 emit(*next_machine_iter, *job_iter);
172 current_load = job_load - frac_load;
175 emit(*machine_iter, *job_iter);
177 current_load = new_load;
180 assert(job_iter == jobs.end());
206 template <
class MachineIterator,
class JobIterator,
class OutputIterator,
207 class GetSpeed,
class GetLoad>
209 const MachineIterator mlast,
210 const JobIterator jfirst,
const JobIterator jlast,
211 OutputIterator result, GetSpeed get_speed,
213 detail::schedule(mfirst, mlast, jfirst, jlast, result, get_speed, get_load,
241 template <
class MachineIterator,
class JobIterator,
class OutputIterator,
242 class GetSpeed,
class GetLoad,
243 class RandomNumberGenerator = std::default_random_engine>
244 void schedule_randomized(
const MachineIterator mfirst,
245 const MachineIterator mlast,
const JobIterator jfirst,
246 const JobIterator jlast, OutputIterator result,
247 GetSpeed get_speed, GetLoad get_load,
248 RandomNumberGenerator &&gen =
249 std::default_random_engine(97345631u)) {
250 typedef typename detail::sched_traits<MachineIterator, JobIterator,
251 GetSpeed, GetLoad> Traits;
252 double alpha = std::uniform_real_distribution<double>()(gen);
253 auto round = [alpha](
typename Traits::load_t fractional_load,
254 typename Traits::load_t total_load) {
255 return total_load * alpha < fractional_load;
257 detail::schedule(mfirst, mlast, jfirst, jlast, result, get_speed, get_load,
264 #endif // PAAL_SCHEDULING_JOBS_HPP
auto make_functor_to_comparator(Functor functor, Compare compare=Compare())
make for functor to comparator
auto irange(T begin, T end)
irange
This file contains set of simple useful functors or functor adapters.
void assign_max(T &t, const T &u)
void assign_min(T &t, const T &u)
auto make_lift_iterator_functor(Functor f)
make function for lift_iterator_functor
Implementation of fractions, which are used only for comparison purposes, and thus they can be used w...
typename std::decay< typename std::result_of< F >::type >::type pure_result_of_t
return pure type of function (decays const and reference)
simple class to represent fraction
void schedule_deterministic(const MachineIterator mfirst, const MachineIterator mlast, const JobIterator jfirst, const JobIterator jlast, OutputIterator result, GetSpeed get_speed, GetLoad get_load)
detail