316 double c,
const std::vector<double>& weight,
317 std::size_t nclasses) {
318 const std::size_t n = jobs.size();
319 std::vector<double> rates(n, 0.0);
320 if (n == 0)
return rates;
331 if (weighted_by_job) {
333 for (
const PsJob& j : jobs) tot += weight[j.
cls];
335 for (std::size_t i = 0; i < n; ++i)
336 rates[i] = std::min(1.0, weight[jobs[i].cls] * c / tot);
339 }
else if (weighted_by_class) {
340 std::vector<int> per_class(nclasses, 0);
341 for (
const PsJob& j : jobs) ++per_class[j.
cls];
343 for (std::size_t k = 0; k < nclasses; ++k)
344 if (per_class[k] > 0) tot += weight[k];
346 for (std::size_t i = 0; i < n; ++i) {
347 const std::size_t k = jobs[i].cls;
348 rates[i] = std::min(1.0, (weight[k] / tot / per_class[k]) * c);
354 const double share = std::min(1.0, c /
static_cast<double>(n));
355 for (std::size_t i = 0; i < n; ++i) rates[i] = share;
362 if (
static_cast<double>(n) <= c) {
363 for (std::size_t i = 0; i < n; ++i) rates[i] = 1.0;
368 double remaining = c;
369 for (std::set<int>::const_iterator it = prios.begin(); it != prios.end(); ++it) {
370 if (remaining <= 0.0)
break;
373 double tot_job_weight = 0.0;
374 std::vector<int> per_class(nclasses, 0);
375 for (
const PsJob& j : jobs)
378 tot_job_weight += weight[j.
cls];
381 const double allocated = std::min(remaining,
static_cast<double>(count));
382 double tot_class_weight = 0.0;
383 for (std::size_t k = 0; k < nclasses; ++k)
384 if (per_class[k] > 0) tot_class_weight += weight[k];
386 for (std::size_t i = 0; i < n; ++i) {
387 if (jobs[i].priority != p)
continue;
388 const std::size_t k = jobs[i].cls;
390 rates[i] = std::min(1.0, weight[k] * allocated / tot_job_weight);
392 rates[i] = std::min(1.0, (weight[k] / tot_class_weight / per_class[k]) * allocated);
394 rates[i] = allocated / count;
396 remaining -= allocated;
412 double c,
double now) {
413 std::vector<double> works = residuals;
414 std::sort(works.begin(), works.end());
415 const std::size_t n = works.size();
416 double cumulative = 0.0, prev = 0.0;
417 for (std::size_t rank = 0; rank < n; ++rank) {
418 const double w = works[rank];
419 const double rate = std::min(1.0, c /
static_cast<double>(n - rank));
420 if (rate > 0.0) cumulative += (w - prev) / rate;
421 if (w >= target_work)
return now + cumulative;
424 return now + cumulative;
444 const Job& arriving,
double c,
double now) {
445 const std::size_t none = in_service.size();
446 if (in_service.empty())
return none;
453 std::size_t best = none;
454 double oldest = std::numeric_limits<double>::infinity();
455 for (std::size_t j = 0; j < in_service.size(); ++j)
456 if (in_service[j].t_arr < oldest) {
457 oldest = in_service[j].t_arr;
464 std::size_t best = none;
465 double oldest = std::numeric_limits<double>::infinity();
466 for (std::size_t j = 0; j < in_service.size(); ++j)
467 if (in_service[j].priority >= arriving.
priority && in_service[j].t_arr < oldest) {
468 oldest = in_service[j].t_arr;
479 std::size_t best = none;
480 for (std::size_t j = 0; j < in_service.size(); ++j) {
481 if (in_service[j].priority <= arriving.
priority)
continue;
482 if (best == none || in_service[j].priority > in_service[best].priority ||
483 (in_service[j].priority == in_service[best].priority &&
484 in_service[j].t_arr > in_service[best].t_arr))
491 std::size_t worst = 0;
492 for (std::size_t j = 1; j < in_service.size(); ++j)
493 if (in_service[j].remaining > in_service[worst].remaining) worst = j;
495 in_service[worst].priority < arriving.
priority)
497 return (arriving.
remaining < in_service[worst].remaining) ? worst : none;
500 std::size_t largest = 0;
501 for (std::size_t j = 1; j < in_service.size(); ++j)
502 if (in_service[j].service > in_service[largest].service) largest = j;
503 return (arriving.
service < in_service[largest].service) ? largest : none;
509 std::size_t most = 0;
510 for (std::size_t j = 1; j < in_service.size(); ++j)
511 if (in_service[j].elapsed > in_service[most].elapsed) most = j;
512 return (in_service[most].elapsed > arriving.
elapsed) ? most : none;
515 std::size_t least = 0;
516 for (std::size_t j = 1; j < in_service.size(); ++j)
517 if (in_service[j].remaining < in_service[least].remaining) least = j;
518 return (arriving.
remaining > in_service[least].remaining) ? least : none;
521 std::vector<double> works;
522 for (
const Job& j : in_service) works.push_back(j.
remaining);
525 std::size_t worst = 0;
526 double worst_vft = -std::numeric_limits<double>::infinity();
527 for (std::size_t j = 0; j < in_service.size(); ++j) {
534 return (arrival_vft < worst_vft) ? worst : none;
double fsp_virtual_finish(const std::vector< double > &residuals, double target_work, double c, double now)
FSP's virtual finish time: when target would finish if the station ran processor sharing from now on.
std::vector< double > ps_shares(lang::SchedStrategy sched, const std::vector< PsJob > &jobs, double c, const std::vector< double > &weight, std::size_t nclasses)
The per-job shares of a sharing discipline, in units of one server.
std::size_t preemption_victim(lang::SchedStrategy sched, const std::vector< Job > &in_service, const Job &arriving, double c, double now)
Which job in service arriving displaces, or in_service.size() for none.