From 534ead4118030cf150c183e83bcbfec057756bc3 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 13 Apr 2005 18:38:55 +0000 Subject: [PATCH] *** empty log message *** svn path=/trunk/boinc/; revision=5846 --- checkin_notes | 12 +++ client/app_control.C | 1 + client/client_state.C | Bin 40828 -> 40715 bytes client/client_state.h | 6 ++ client/client_types.C | 7 +- client/client_types.h | 1 + client/cs_apps.C | 57 ++++++++++-- client/cs_scheduler.C | 202 ++++++++++++++++++++++++++++++++++++------ client/scheduler_op.C | 10 +-- client/scheduler_op.h | 2 +- lib/boinc_win.h | 2 + lib/prefs.C | 6 ++ lib/prefs.h | 1 + 13 files changed, 266 insertions(+), 41 deletions(-) diff --git a/checkin_notes b/checkin_notes index 7da3674e98..3ce4de52db 100755 --- a/checkin_notes +++ b/checkin_notes @@ -27123,3 +27123,15 @@ Rom 12 April 2005 BOINCTaskCtrl.cpp lib/ gui_rpc_client.C + +David 13 April 2005 + client/ + app_control.C + client_state.C,h + client_types.C,h + cs_apps.C + cs_scheduler.C + scheduler_op.C,h + lib/ + boinc_win.h + prefs.C,h diff --git a/client/app_control.C b/client/app_control.C index 9a2ea5c99c..9cc514432f 100644 --- a/client/app_control.C +++ b/client/app_control.C @@ -673,6 +673,7 @@ int ACTIVE_TASK_SET::abort_project(PROJECT* project) { task_iter++; } } + project->long_term_debt = 0; return 0; } diff --git a/client/client_state.C b/client/client_state.C index 12a8e6bb6b052610d94c1b8dabefe89f35f60288..4c5720477b36c11835a29f890f339c358853c7b1 100644 GIT binary patch literal 40715 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 V{&gqMc`W|gzZ?wyW$opY{{e5ut%d*q diff --git a/client/client_state.h b/client/client_state.h index dea5c67a80..2953409e4e 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -147,6 +147,8 @@ private: // double cpu_sched_last_time; double cpu_sched_work_done_this_period; + bool work_fetch_no_new_work; + bool cpu_crunch_nearest_first; // --------------- client_state.C: public: @@ -219,6 +221,7 @@ private: int app_finished(ACTIVE_TASK&); void assign_results_to_projects(); bool schedule_largest_debt_project(double expected_pay_off); + bool schedule_nearest_deadline_project(double expected_pay_off); bool start_apps(); bool schedule_cpus(double); bool handle_finished_apps(double); @@ -282,6 +285,9 @@ private: bool scheduler_rpc_poll(double); double ettprc(PROJECT*, int); double avg_proc_rate(PROJECT*); + bool should_get_work(); + bool no_work_for_a_cpu(); + void set_cpu_scheduler_modes(); // --------------- cs_statefile.C: public: diff --git a/client/client_types.C b/client/client_types.C index 6adaf425c0..739af87fd8 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -86,6 +86,7 @@ void PROJECT::init() { anonymous_platform = false; non_cpu_intensive = false; debt = 0; + long_term_debt = 0; send_file_list = false; suspended_via_gui = false; dont_request_more_work = false; @@ -176,6 +177,7 @@ int PROJECT::parse_state(MIOFILE& in) { else if (match_tag(buf, "")) deletion_policy_expire = true; #endif else if (parse_double(buf, "", debt)) continue; + else if (parse_double(buf, "", long_term_debt)) continue; else if (parse_double(buf, "", x)) continue; // not authoritative else scope_messages.printf("PROJECT::parse_state(): unrecognized: %s\n", buf); } @@ -221,6 +223,7 @@ int PROJECT::write_state(MIOFILE& out, bool gui_rpc) { " %d\n" " %f\n" " %f\n" + " %f\n" " %f\n" "%s%s%s%s%s%s", master_url, @@ -247,6 +250,7 @@ int PROJECT::write_state(MIOFILE& out, bool gui_rpc) { master_fetch_failures, min_rpc_time, debt, + long_term_debt, resource_share, master_url_fetch_pending?" \n":"", sched_rpc_pending?" \n":"", @@ -314,6 +318,7 @@ void PROJECT::copy_state_fields(PROJECT& p) { sched_rpc_pending = p.sched_rpc_pending; safe_strcpy(code_sign_key, p.code_sign_key); debt = p.debt; + long_term_debt = p.long_term_debt; send_file_list = p.send_file_list; non_cpu_intensive = p.non_cpu_intensive; suspended_via_gui = p.suspended_via_gui; @@ -657,7 +662,7 @@ int FILE_INFO::write_gui(MIOFILE& out) { " %f\n" " %f\n" " %d\n", - project->master_url, + project->master_url, project->project_name, name, nbytes, diff --git a/client/client_types.h b/client/client_types.h index 356660ff00..3d762fe42d 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -232,6 +232,7 @@ public: struct RESULT *next_runnable_result; // the next result to run for this project // the following used by work-fetch algorithm + double long_term_debt; // how much CPU time we owe this project in the long term (secs) double work_request; // the unit is "normalized CPU seconds", // i.e. the work should take 1 CPU on this host diff --git a/client/cs_apps.C b/client/cs_apps.C index 6082812d09..a3fb5c5fce 100644 --- a/client/cs_apps.C +++ b/client/cs_apps.C @@ -347,6 +347,36 @@ bool CLIENT_STATE::schedule_largest_debt_project(double expected_pay_off) { best_project->next_runnable_result = 0; return true; } +// The CPU scheduler is in panic mode. +// Schedule the active task with the earliest deadline +// Return true iff a task was scheduled. +// +bool CLIENT_STATE::schedule_nearest_deadline_project(double expected_pay_off) { + PROJECT *best_project = NULL; + RESULT *best_result = NULL; + double earliest_deadline; + bool first = true; + unsigned int i; + + for (i=0; i < results.size(); ++i) { + RESULT *r = results[i]; + if (RESULT_FILES_DOWNLOADED != r->state) continue; + if (r->project->non_cpu_intensive) continue; + if (r->already_selected) continue; + if (first || r->report_deadline < earliest_deadline) { + first = false; + best_project = r->project; + best_result = r; + earliest_deadline = r->report_deadline; + } + } + if (!best_result) return false; + + schedule_result(best_result); + best_project->anticipated_debt -= expected_pay_off; + best_project->next_runnable_result = 0; + return true; +} // Schedule active tasks to be run and preempted. // @@ -399,6 +429,8 @@ bool CLIENT_STATE::schedule_cpus(double now) { results[i]->already_selected = false; } + set_cpu_scheduler_modes(); + // do work accounting for active tasks // for (i=0; inon_cpu_intensive) continue; + count_cpu_intensive++; + double debt_inc = + (p->resource_share/local_total_resource_share) + * cpu_sched_work_done_this_period + - p->work_done_this_period; + p->long_term_debt += debt_inc; + total_long_term_debt += p->long_term_debt; if (!p->next_runnable_result) { p->debt = 0; p->anticipated_debt = 0; - } else { - p->debt += - (p->resource_share/local_total_resource_share) - * cpu_sched_work_done_this_period - - p->work_done_this_period; + } else { + p->debt += debt_inc; if (first) { first = false; min_debt = p->debt; @@ -452,6 +490,8 @@ bool CLIENT_STATE::schedule_cpus(double now) { ); } + double avg_long_term_debt = total_long_term_debt / count_cpu_intensive; + // Normalize debts to zero // for (i=0; idebt); p->next_runnable_result = NULL; } + p->long_term_debt -= avg_long_term_debt; } // schedule tasks for projects in order of decreasing anticipated debt @@ -477,7 +518,11 @@ bool CLIENT_STATE::schedule_cpus(double now) { expected_pay_off = cpu_sched_work_done_this_period / ncpus; for (j=0; j #include #include +#include +#include #endif #include "crypt.h" @@ -68,13 +70,17 @@ const int SECONDS_BEFORE_REPORTING_MIN_RPC_TIME_AGAIN = 60*60; // #define REPORT_DEADLINE_CUSHION SECONDS_PER_DAY +// try to maintain no more than this load factor on the CPU. +// +#define MAX_CPU_LOAD_FACTOR 0.8 + static int proj_min_results(PROJECT* p, int ncpus) { return (int)(ceil(ncpus*p->resource_share/trs)); } void PROJECT::set_min_rpc_time(double future_time) { - if (future_time > min_rpc_time) { - min_rpc_time = future_time; - } + if (future_time > min_rpc_time) { + min_rpc_time = future_time; + } min_report_min_rpc_time = 0; } @@ -139,7 +145,7 @@ PROJECT* CLIENT_STATE::next_project_sched_rpc_pending() { // 4) has dont_request_more_work == false // PROJECT* CLIENT_STATE::next_project_need_work(PROJECT *old) { - PROJECT *p; + PROJECT *p, *p_prospect = NULL; double now = dtime(); unsigned int i; bool found_old = (old == 0); @@ -153,11 +159,13 @@ PROJECT* CLIENT_STATE::next_project_need_work(PROJECT *old) { if (p->waiting_until_min_rpc_time(now)) continue; if (p->suspended_via_gui) continue; if (p->dont_request_more_work) continue; + if (p->long_term_debt < 0 && !no_work_for_a_cpu()) continue; + if (p_prospect && p->long_term_debt < p_prospect->long_term_debt && !p->non_cpu_intensive) continue; if (found_old && p->work_request > 0) { - return p; + p_prospect = p; } } - return 0; + return p_prospect; } // Write a scheduler request to a disk file @@ -194,22 +202,22 @@ int CLIENT_STATE::make_scheduler_request(PROJECT* p, double work_req) { p->authenticator, p->hostid, p->rpc_seqno, - p->anonymous_platform?"anonymous":platform_name, + p->anonymous_platform?"anonymous":platform_name, core_client_major_version, core_client_minor_version, work_req, p->resource_share / trs, ettprc(p, proj_min_results(p, ncpus)-1) ); - if (p->anonymous_platform) { - fprintf(f, " \n"); - for (i=0; iproject != p) continue; - avp->write(mf); - } - fprintf(f, " \n"); - } + if (p->anonymous_platform) { + fprintf(f, " \n"); + for (i=0; iproject != p) continue; + avp->write(mf); + } + fprintf(f, " \n"); + } #if 0 anything_free(free); fprintf(f, " %f\n", free); @@ -352,7 +360,7 @@ double CLIENT_STATE::avg_proc_rate(PROJECT *p) { double running_frac = time_stats.on_frac * time_stats.active_frac; if (running_frac < 0.1) running_frac = 0.1; if (running_frac > 1) running_frac = 1; - return (p->resource_share / trs) * ncpus * running_frac; + return (p ? (p->resource_share / trs) : 1) * ncpus * running_frac; } // "estimated time to project result count" @@ -411,6 +419,7 @@ int CLIENT_STATE::compute_work_requests() { if (p->min_rpc_time >= now) continue; if (p->dont_request_more_work) continue; if (p->suspended_via_gui) continue; + if (p->long_term_debt < 0 && !no_work_for_a_cpu()) continue; int min_results = proj_min_results(p, ncpus); double estimated_time_to_starvation = ettprc(p, min_results-1); @@ -471,7 +480,9 @@ bool CLIENT_STATE::scheduler_rpc_poll(double now) { switch(scheduler_op->state) { case SCHEDULER_OP_STATE_IDLE: if (network_suspended) break; - urgency = compute_work_requests(); + if (should_get_work()) { + urgency = compute_work_requests(); + } // highest priority is to report overdue results // @@ -486,14 +497,11 @@ bool CLIENT_STATE::scheduler_rpc_poll(double now) { global_prefs.work_buf_min_days ); } else if (urgency == NEED_WORK_IMMEDIATELY) { - msg_printf(NULL, MSG_INFO, - "Insufficient work; requesting more" - ); - } - scheduler_op->init_get_work(); +} + scheduler_op->init_get_work(false); action = true; } else if ((p=next_project_master_pending())) { - scheduler_op->init_get_work(); + scheduler_op->init_get_work(true); action = true; } else if ((p=next_project_sched_rpc_pending())) { scheduler_op->init_return_results(p); @@ -559,7 +567,7 @@ int CLIENT_STATE::handle_scheduler_reply( // see if we have a new venue from this project // - if (strlen(sr.host_venue) && strcmp(project->host_venue, sr.host_venue)) { + if (strlen(sr.host_venue) && strcmp(project->host_venue, sr.host_venue)) { safe_strcpy(project->host_venue, sr.host_venue); msg_printf(project, MSG_INFO, "New host venue: %s", sr.host_venue); update_project_prefs = true; @@ -596,10 +604,10 @@ int CLIENT_STATE::handle_scheduler_reply( sr.global_prefs_xml ); fclose(f); - update_global_prefs = true; - } + update_global_prefs = true; + } - if (update_global_prefs) { + if (update_global_prefs) { bool found_venue; retval = global_prefs.parse_file( GLOBAL_PREFS_FILE_NAME, project->host_venue, found_venue @@ -813,4 +821,142 @@ int CLIENT_STATE::handle_scheduler_reply( return 0; } +// Prevents work from being downloaded if there may be too much if more is downloaded. +bool CLIENT_STATE::should_get_work() { + // if there are fewer wus available then CPUS, then we need more work. + if (no_work_for_a_cpu()) return true; + + double tot_cpu_time_remaining = 0; + for (unsigned int i = 0; i < results.size();++i) { + tot_cpu_time_remaining += results[i]->estimated_cpu_time_remaining(); + } + if (tot_cpu_time_remaining < global_prefs.work_buf_min_days * SECONDS_PER_DAY) return true; + + // if the CPU started this time period over loaded, let it crunch for a while to get out + // of the CPU overload status. + if (!work_fetch_no_new_work) { + set_cpu_scheduler_modes(); + } + bool ret = !work_fetch_no_new_work; + + return ret; +} + +// CPU idle check. +bool CLIENT_STATE::no_work_for_a_cpu() { + return (unsigned int)ncpus > results.size(); +} + +// sets a couple of variables showing the needed state for the CPU scheduler. +void CLIENT_STATE::set_cpu_scheduler_modes() { + std::map < double, RESULT * > results_by_deadline; + std::set < PROJECT * > projects_with_work; + // cheap sorting trick. This works on every implementation of std::map that I know of, and + // it will be hard to avoid this behavour since inserts, lookups and deletes are all guaranteed lg(N) + std::vector::iterator it_u; + for (it_u = results.begin() ; it_u != results.end(); ++it_u) { + if (RESULT_COMPUTE_ERROR > (*it_u)->state && !(*it_u)->project->non_cpu_intensive) { + results_by_deadline[(*it_u)->report_deadline] = *it_u; + projects_with_work.insert((*it_u)->project); + } + } + + bool should_not_fetch_work = false; + bool should_crunch_nearest = false; + double now; + double frac_booked; + std::vector booked_to; + now = dtime(); + frac_booked = 0; + for (int i = 0; i < ncpus; ++i) booked_to.push_back(now); + + std::map::iterator it; + double up_frac = avg_proc_rate(0); + for (it = results_by_deadline.begin(); it != results_by_deadline.end() && !should_not_fetch_work; ++it) { + RESULT *r = (*it).second; + if (RESULT_COMPUTE_ERROR > ((*it).second)->state) { + double lowest_book = booked_to[0]; + int lowest_booked_cpu = 0; + for(int i = 1; i < ncpus; ++i) + { + if (booked_to[i] < lowest_book) { + lowest_book = booked_to[i]; + lowest_booked_cpu = i; + } + } + booked_to[lowest_booked_cpu] += ((*it).second)->estimated_cpu_time_remaining(); + + // Are the deadlines too tight to meet reliably? + if (booked_to[lowest_booked_cpu] - now > (r->report_deadline - now) * MAX_CPU_LOAD_FACTOR * up_frac) { + + should_not_fetch_work = true; + should_crunch_nearest = true; + if (!cpu_crunch_nearest_first || !work_fetch_no_new_work) { + msg_printf(NULL, MSG_INFO, + "Work fetch policy, CPU Scheduler policy - Overbooked."); + } + } + // Is the deadline soon? + if (r->report_deadline - now < 60 * 60 * 24) { + should_crunch_nearest = true; + if (!cpu_crunch_nearest_first) { + msg_printf(NULL, MSG_INFO, + "CPU Scheduler policy - Deadline < 1 day."); + } + } + + // is there a deadline < twice the users connect period? If so, we should crunch nearest so + // that it can be returned the next connection if possible. + if (r->report_deadline - now < global_prefs.work_buf_min_days * SECONDS_PER_DAY * 2) { + should_crunch_nearest = true; + if (!cpu_crunch_nearest_first) { + msg_printf(NULL, MSG_INFO, + "CPU Scheduler policy - deadline < 2 * queue size."); + } + } + + // is it getting a little uncomfortable? + frac_booked += r->estimated_cpu_time_remaining() / (r->report_deadline - now); + } + } + + // Is it getting a little uncomfortable? + if (frac_booked > MAX_CPU_LOAD_FACTOR * up_frac * ncpus) { + should_not_fetch_work = true; + if (!work_fetch_no_new_work) { + msg_printf(NULL, MSG_INFO, + "Work fetch policy - uncomfortable."); + } + } + + // check for too many projects that have work + if (projects_with_work.size() >= (unsigned int)global_prefs.max_projects_on_client) { + should_not_fetch_work = true; + if (!work_fetch_no_new_work) { + msg_printf(NULL, MSG_INFO, + "Work fetch policy - max projects exceeded."); + } + } + + if (work_fetch_no_new_work && !should_not_fetch_work) { // display only when the policy changes to avoid once per second + msg_printf(NULL, MSG_INFO, + "Work fetch policy - work fetch now allowed."); + } + if (!work_fetch_no_new_work && should_not_fetch_work) { // display only when the policy changes to avoid once per second + msg_printf(NULL, MSG_INFO, + "Work fetch policy - no work fetch allowed."); + } + if (cpu_crunch_nearest_first && !should_crunch_nearest) { // display only when the policy changes to avoid once per second + msg_printf(NULL, MSG_INFO, + "CPU scheduler policy - crunch highest debt first (normal mode)."); + } + if (!cpu_crunch_nearest_first && should_crunch_nearest) { // display only when the policy changes to avoid once per second + msg_printf(NULL, MSG_INFO, + "CPU scheduler policy - crunch earliest deadline first (panic mode)."); + } + + work_fetch_no_new_work = should_not_fetch_work; + cpu_crunch_nearest_first = should_crunch_nearest; +} + const char *BOINC_RCSID_d35a4a7711 = "$Id$"; diff --git a/client/scheduler_op.C b/client/scheduler_op.C index 2263cffb93..8caf5cc468 100644 --- a/client/scheduler_op.C +++ b/client/scheduler_op.C @@ -80,14 +80,14 @@ bool SCHEDULER_OP::check_master_fetch_start() { // PRECONDITION: compute_work_requests() has been called // to fill in PROJECT::work_request // -int SCHEDULER_OP::init_get_work() { +int SCHEDULER_OP::init_get_work(bool master_file_only) { int retval; char err_msg[256]; double ns; must_get_work = true; project = gstate.next_project_need_work(0); - if (project) { + if (project && !master_file_only) { ns = project->work_request; msg_printf(project, MSG_INFO, "Requesting %.2f seconds of work", ns); retval = init_op_project(ns); @@ -614,14 +614,14 @@ int SCHEDULER_REPLY::parse(FILE* in, PROJECT* project) { project->write_statistics_file(); - return 0; + return 0; } else if (parse_str(buf, "", project->project_name, sizeof(project->project_name))) continue; - else if (parse_str(buf, "", project->user_name, sizeof(project->user_name))) continue; + else if (parse_str(buf, "", project->user_name, sizeof(project->user_name))) continue; else if (parse_double(buf, "", project->user_total_credit)) continue; else if (parse_double(buf, "", project->user_expavg_credit)) continue; else if (parse_double(buf, "", project->user_create_time)) continue; - else if (parse_str(buf, "", project->team_name, sizeof(project->team_name))) continue; + else if (parse_str(buf, "", project->team_name, sizeof(project->team_name))) continue; else if (parse_int(buf, "", hostid)) continue; else if (parse_double(buf, "", project->host_total_credit)) continue; else if (parse_double(buf, "", project->host_expavg_credit)) continue; diff --git a/client/scheduler_op.h b/client/scheduler_op.h index 8978edd5ad..328e16d6bd 100644 --- a/client/scheduler_op.h +++ b/client/scheduler_op.h @@ -73,7 +73,7 @@ struct SCHEDULER_OP { SCHEDULER_OP(HTTP_OP_SET*); bool poll(); - int init_get_work(); + int init_get_work(bool master_file_only); int init_return_results(PROJECT*); int init_op_project(double ns); int init_master_fetch(); diff --git a/lib/boinc_win.h b/lib/boinc_win.h index edbd3e3983..da083e014d 100644 --- a/lib/boinc_win.h +++ b/lib/boinc_win.h @@ -115,6 +115,8 @@ #include #include #include +#include +#include #endif diff --git a/lib/prefs.C b/lib/prefs.C index 0adb75b97f..0bf0411785 100644 --- a/lib/prefs.C +++ b/lib/prefs.C @@ -51,6 +51,7 @@ void GLOBAL_PREFS::defaults() { dont_verify_images = false; work_buf_min_days = 0.1; max_cpus = 1; + max_projects_on_client = 5; cpu_scheduling_period_minutes = 60; disk_interval = 60; disk_max_used_gb = 1; @@ -175,6 +176,9 @@ int GLOBAL_PREFS::parse(FILE* in, const char* host_venue, bool& found_venue) { } else if (parse_int(buf, "", max_cpus)) { if (max_cpus < 1) max_cpus = 1; continue; + } else if (parse_int(buf, "", max_projects_on_client)) { + if (max_projects_on_client < 1) max_projects_on_client = 1; + continue; } else if (parse_double(buf, "", disk_interval)) { if (disk_interval<0) disk_interval = 0; continue; @@ -235,6 +239,7 @@ int GLOBAL_PREFS::write(FILE* f) { "%s%s%s%s%s%s" " %f\n" " %d\n" + " %d\n" " %f\n" " %f\n" " %f\n" @@ -258,6 +263,7 @@ int GLOBAL_PREFS::write(FILE* f) { dont_verify_images?" \n":"", work_buf_min_days, max_cpus, + max_projects_on_client, cpu_scheduling_period_minutes, disk_interval, disk_max_used_gb, diff --git a/lib/prefs.h b/lib/prefs.h index 3fd12e9c33..db9eebf90b 100644 --- a/lib/prefs.h +++ b/lib/prefs.h @@ -46,6 +46,7 @@ struct GLOBAL_PREFS { bool dont_verify_images; double work_buf_min_days; int max_cpus; + int max_projects_on_client; double cpu_scheduling_period_minutes; double disk_interval; double disk_max_used_gb;