347 double c,
const std::vector<double>& weight,
348 std::size_t nclasses) {
349 const std::size_t n = jobs.size();
350 std::vector<double> rates(n, 0.0);
351 if (n == 0)
return rates;
362 if (weighted_by_job) {
364 for (
const PsJob& j : jobs) tot += weight[j.
cls];
366 for (std::size_t i = 0; i < n; ++i)
367 rates[i] = std::min(1.0, weight[jobs[i].cls] * c / tot);
370 }
else if (weighted_by_class) {
371 std::vector<int> per_class(nclasses, 0);
372 for (
const PsJob& j : jobs) ++per_class[j.
cls];
374 for (std::size_t k = 0; k < nclasses; ++k)
375 if (per_class[k] > 0) tot += weight[k];
377 for (std::size_t i = 0; i < n; ++i) {
378 const std::size_t k = jobs[i].cls;
379 rates[i] = std::min(1.0, (weight[k] / tot / per_class[k]) * c);
385 const double share = std::min(1.0, c /
static_cast<double>(n));
386 for (std::size_t i = 0; i < n; ++i) rates[i] = share;
393 if (
static_cast<double>(n) <= c) {
394 for (std::size_t i = 0; i < n; ++i) rates[i] = 1.0;
399 double remaining = c;
400 for (std::set<int>::const_iterator it = prios.begin(); it != prios.end(); ++it) {
401 if (remaining <= 0.0)
break;
404 double tot_job_weight = 0.0;
405 std::vector<int> per_class(nclasses, 0);
406 for (
const PsJob& j : jobs)
409 tot_job_weight += weight[j.
cls];
412 const double allocated = std::min(remaining,
static_cast<double>(count));
413 double tot_class_weight = 0.0;
414 for (std::size_t k = 0; k < nclasses; ++k)
415 if (per_class[k] > 0) tot_class_weight += weight[k];
417 for (std::size_t i = 0; i < n; ++i) {
418 if (jobs[i].priority != p)
continue;
419 const std::size_t k = jobs[i].cls;
421 rates[i] = std::min(1.0, weight[k] * allocated / tot_job_weight);
423 rates[i] = std::min(1.0, (weight[k] / tot_class_weight / per_class[k]) * allocated);
425 rates[i] = allocated / count;
427 remaining -= allocated;
443 double c,
double now) {
444 std::vector<double> works = residuals;
445 std::sort(works.begin(), works.end());
446 const std::size_t n = works.size();
447 double cumulative = 0.0, prev = 0.0;
448 for (std::size_t rank = 0; rank < n; ++rank) {
449 const double w = works[rank];
450 const double rate = std::min(1.0, c /
static_cast<double>(n - rank));
451 if (rate > 0.0) cumulative += (w - prev) / rate;
452 if (w >= target_work)
return now + cumulative;
455 return now + cumulative;
488 const std::vector<double>& started,
const Job& arriving,
489 double c,
double now) {
490 const std::size_t none = in_service.size();
491 if (in_service.empty())
return none;
498 std::size_t best = none;
499 double oldest = std::numeric_limits<double>::infinity();
500 for (std::size_t j = 0; j < in_service.size(); ++j)
501 if (in_service[j].t_arr < oldest) {
502 oldest = in_service[j].t_arr;
512 std::size_t best = none;
513 for (std::size_t j = 0; j < in_service.size(); ++j) {
514 if (in_service[j].priority <= arriving.
priority)
continue;
515 if (best == none || in_service[j].priority > in_service[best].priority ||
516 (in_service[j].priority == in_service[best].priority &&
517 in_service[j].t_arr < in_service[best].t_arr))
520 if (best != none)
return best;
521 for (std::size_t j = 0; j < in_service.size(); ++j)
522 if (in_service[j].priority == arriving.
priority &&
523 (best == none || started[j] < started[best]))
537 std::size_t best = none;
538 for (std::size_t j = 0; j < in_service.size(); ++j) {
539 if (in_service[j].priority <= arriving.
priority)
continue;
540 if (best == none || in_service[j].priority > in_service[best].priority ||
541 (in_service[j].priority == in_service[best].priority &&
542 in_service[j].t_arr > in_service[best].t_arr))
555 std::size_t worst = 0;
556 for (std::size_t j = 1; j < in_service.size(); ++j) {
557 if (prio && in_service[j].priority != in_service[worst].priority) {
558 if (in_service[j].priority > in_service[worst].priority) worst = j;
559 }
else if (in_service[j].remaining > in_service[worst].remaining) {
563 if (prio && arriving.
priority != in_service[worst].priority)
564 return (arriving.
priority < in_service[worst].priority) ? worst : none;
565 return (arriving.
remaining < in_service[worst].remaining) ? worst : none;
568 std::size_t largest = 0;
569 for (std::size_t j = 1; j < in_service.size(); ++j)
570 if (in_service[j].service > in_service[largest].service) largest = j;
571 return (arriving.
service < in_service[largest].service) ? largest : none;
577 std::size_t most = 0;
578 for (std::size_t j = 1; j < in_service.size(); ++j)
579 if (in_service[j].elapsed > in_service[most].elapsed) most = j;
580 return (in_service[most].elapsed > arriving.
elapsed) ? most : none;
583 std::size_t least = 0;
584 for (std::size_t j = 1; j < in_service.size(); ++j)
585 if (in_service[j].remaining < in_service[least].remaining) least = j;
586 return (arriving.
remaining > in_service[least].remaining) ? least : none;
589 std::vector<double> works;
590 for (
const Job& j : in_service) works.push_back(j.
remaining);
593 std::size_t worst = 0;
594 double worst_vft = -std::numeric_limits<double>::infinity();
595 for (std::size_t j = 0; j < in_service.size(); ++j) {
602 return (arrival_vft < worst_vft) ? worst : none;
607 std::size_t latest = 0;
608 for (std::size_t j = 1; j < in_service.size(); ++j)
609 if (in_service[j].deadline > in_service[latest].deadline) latest = j;
610 return (arriving.
deadline < in_service[latest].deadline) ? latest : none;
std::size_t preemption_victim(lang::SchedStrategy sched, const std::vector< Job > &in_service, const std::vector< double > &started, const Job &arriving, double c, double now)
Which job in service arriving displaces, or in_service.size() for 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.