// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// BOINC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with BOINC. If not, see .
// Work fetch logic for CPU, GPU, and other processing resources.
// See http://boinc.berkeley.edu/trac/wiki/GpuWorkFetch
#ifndef _WORK_FETCH_
#define _WORK_FETCH_
#include
#define RSC_TYPE_ANY 0
#define RSC_TYPE_CPU 1
#define RSC_TYPE_CUDA 2
#define RSC_TYPE_ATI 3
struct PROJECT;
struct RESULT;
struct ACTIVE_TASK;
struct RSC_WORK_FETCH;
struct SCHEDULER_REPLY;
// state per (resource, project) pair
//
struct RSC_PROJECT_WORK_FETCH {
// the following are persistent (saved in state file)
double backoff_time;
double backoff_interval;
double long_term_debt;
double short_term_debt;
// the following used by debt accounting
double anticipated_debt;
// short-term debt, adjusted by scheduled jobs
double secs_this_debt_interval;
inline void reset_debt_accounting() {
secs_this_debt_interval = 0;
}
double queue_est;
// an estimate of instance-secs of queued work;
// a temp used in computing overall debts
bool anon_skip;
// set if this project is anonymous platform
// and it has no app version that uses this resource
// the following are used by rr_simulation()
//
double runnable_share;
// this project's share relative to projects that have
// nearly runnable jobs for this resource;
// determines processing rate for CPU
double fetchable_share;
// this project's share relative to projects from which
// we could probably get work for this resource;
// determines how many instances this project deserves
bool has_runnable_jobs;
double sim_nused;
double nused_total; // sum of instances over all runnable jobs
int deadlines_missed;
int deadlines_missed_copy;
// copy of the above used during schedule_cpus()
RSC_PROJECT_WORK_FETCH() {
memset(this, 0, sizeof(*this));
}
// whether this project should accumulate debt for this resource
//
bool debt_eligible(PROJECT*, RSC_WORK_FETCH&);
inline void zero_debt() {
long_term_debt = 0;
short_term_debt = 0;
}
inline void reset() {
backoff_time = 0;
backoff_interval = 0;
long_term_debt = 0;
short_term_debt = 0;
anticipated_debt = 0;
}
bool may_have_work;
bool compute_may_have_work(PROJECT*, int rsc_type);
void backoff(PROJECT*, const char*);
void rr_init(PROJECT*, int rsc_type);
void clear_backoff() {
backoff_time = 0;
backoff_interval = 0;
}
bool overworked();
};
// estimate the time a resources will be saturated
// with high-priority jobs.
//
struct BUSY_TIME_ESTIMATOR {
std::vector busy_time;
int ninstances;
inline void reset() {
for (int i=0; i pending;
BUSY_TIME_ESTIMATOR busy_time_estimator;
void init(int t, int n, double sp) {
rsc_type = t;
ninstances = n;
relative_speed = sp;
busy_time_estimator.init(n);
}
// the following specify the work request for this resource
//
double req_secs;
double req_instances;
// debt accounting
double secs_this_debt_interval;
inline void reset_debt_accounting() {
this->secs_this_debt_interval = 0;
}
void rr_init();
void accumulate_shortfall(double d_time);
void update_saturated_time(double dt);
void update_busy_time(double dur, double nused);
PROJECT* choose_project(int);
void accumulate_debt();
RSC_PROJECT_WORK_FETCH& project_state(PROJECT*);
void update_long_term_debts();
void update_short_term_debts();
void print_state(const char*);
void clear_request();
void set_request(PROJECT*, bool allow_overworked);
bool may_have_work(PROJECT*);
RSC_WORK_FETCH() {
rsc_type = 0;
ninstances = 0;
relative_speed = 0;
shortfall = 0;
nidle_now = 0;
sim_nused = 0;
total_fetchable_share = 0;
total_runnable_share = 0;
saturated_time = 0;
deadline_missed_instances = 0;
}
};
// per project state
//
struct PROJECT_WORK_FETCH {
double overall_debt;
bool can_fetch_work;
bool compute_can_fetch_work(PROJECT*);
bool has_runnable_jobs;
PROJECT_WORK_FETCH() {
memset(this, 0, sizeof(*this));
}
void reset(PROJECT*);
};
// global work fetch state
//
struct WORK_FETCH {
void set_overall_debts();
PROJECT* choose_project();
// find a project to ask for work
PROJECT* non_cpu_intensive_project_needing_work();
void compute_work_request(PROJECT*);
// we're going to contact this project anyway;
// decide how much work to task for
void accumulate_inst_sec(ACTIVE_TASK*, double dt);
void write_request(FILE*, PROJECT*);
void handle_reply(
PROJECT*, SCHEDULER_REPLY*, std::vectornew_results
);
void set_initial_work_request();
void set_all_requests(PROJECT*);
void print_state();
void init();
void rr_init();
void clear_request();
void compute_shares();
void zero_debts();
};
extern RSC_WORK_FETCH cuda_work_fetch;
extern RSC_WORK_FETCH ati_work_fetch;
extern RSC_WORK_FETCH cpu_work_fetch;
extern WORK_FETCH work_fetch;
#endif