From 77c4dd7b327f29506f1ab5f88fbeded05478c0f0 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 2 May 2014 23:11:34 -0700 Subject: [PATCH] API/client: let apps say that fraction done is precise Currently the duration estimate for a task is a combination of - a static estimate, based on wu.rsc_fpops_est and the estimated FLOPS - a dynamic estimate, based on fraction done (FD) and elapsed time The weighting of the dynamic estimate is FD^2; the assumption is that fraction done is imprecise and improves toward the end of a task. This isn't ideal for apps that can supply accurate FD. Solution: add a new API function boinc_fraction_done_exact(). This notifies the client that the FD is accurate, and that it should use only the dynamic estimate. (New clients will do this; old clients will use the FD as the currently do). --- api/boinc_api.cpp | 12 ++++++++++++ api/boinc_api.h | 1 + client/app.h | 2 ++ client/app_control.cpp | 1 + client/work_fetch.cpp | 12 ++++++++++-- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/api/boinc_api.cpp b/api/boinc_api.cpp index 813f47b84c..1b15a7ca00 100644 --- a/api/boinc_api.cpp +++ b/api/boinc_api.cpp @@ -127,6 +127,7 @@ APP_CLIENT_SHM* app_client_shm = 0; static volatile int time_until_checkpoint; // time until enable checkpoint static volatile double fraction_done; +static volatile bool fd_exact = false; static volatile double last_checkpoint_cpu_time; static volatile bool ready_to_checkpoint = false; static volatile int in_critical_section = 0; @@ -383,6 +384,9 @@ static bool update_app_progress(double cpu_t, double cp_cpu_t) { sprintf(buf, "%e\n", fdone); strlcat(msg_buf, buf, sizeof(msg_buf)); } + if (fd_exact) { + strlcat(msg_buf, "\n", sizeof(msg_buf)); + } if (bytes_sent) { sprintf(buf, "%f\n", bytes_sent); strlcat(msg_buf, buf, sizeof(msg_buf)); @@ -849,6 +853,8 @@ int boinc_parse_init_data_file() { return 0; } +// used by wrappers +// int boinc_report_app_status_aux( double cpu_time, double checkpoint_cpu_time, @@ -1429,6 +1435,12 @@ int boinc_fraction_done(double x) { return 0; } +int boinc_fraction_done_exact(double x) { + fraction_done = x; + fd_exact = true; + return 0; +} + int boinc_receive_trickle_down(char* buf, int len) { std::string filename; char path[MAXPATHLEN]; diff --git a/api/boinc_api.h b/api/boinc_api.h index 1ffbf33fd5..870ab7de47 100644 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -92,6 +92,7 @@ extern int boinc_send_trickle_up(char* variety, char* text); extern int boinc_set_min_checkpoint_period(int); extern int boinc_checkpoint_completed(void); extern int boinc_fraction_done(double); +extern int boinc_fraction_done_exact(double); extern int boinc_suspend_other_activities(void); extern int boinc_resume_other_activities(void); extern int boinc_report_app_status( diff --git a/client/app.h b/client/app.h index 8221f8c7fe..a1bcdde1e5 100644 --- a/client/app.h +++ b/client/app.h @@ -108,6 +108,8 @@ struct ACTIVE_TASK { // will be zero if the app doesn't use this call double fraction_done_elapsed_time; // elapsed time when fraction done was last reported + bool fraction_done_exact; + // true if app thinks fraction done is accurate int scheduler_state; int next_scheduler_state; // temp int signal; diff --git a/client/app_control.cpp b/client/app_control.cpp index 964c4a6f99..5af52fca8c 100644 --- a/client/app_control.cpp +++ b/client/app_control.cpp @@ -1349,6 +1349,7 @@ bool ACTIVE_TASK::get_app_status_msg() { bytes_received_episode = dtemp; } parse_int(msg_buf, "", want_network); + parse_bool(msg_buf, "fd_exact", fraction_done_exact); if (parse_int(msg_buf, "", other_pid)) { // for now, we handle only one of these other_pids.clear(); diff --git a/client/work_fetch.cpp b/client/work_fetch.cpp index 18e7eba0d5..3e01020676 100644 --- a/client/work_fetch.cpp +++ b/client/work_fetch.cpp @@ -1052,10 +1052,18 @@ void CLIENT_STATE::compute_nuploading_results() { double ACTIVE_TASK::est_dur() { if (fraction_done >= 1) return elapsed_time; double wu_est = result->estimated_runtime(); - if (fraction_done <= 0) return wu_est; if (wu_est < elapsed_time) wu_est = elapsed_time; + if (fraction_done <= 0) return wu_est; double frac_est = fraction_done_elapsed_time / fraction_done; - double fd_weight = fraction_done * fraction_done; + + // if app says fraction done is accurate, just use it + // + if (fraction_done_exact) return frac_est; + + // weighting of dynamic estimate is the fraction done + // i.e. when fraction done is 0.5, weighting is 50/50 + // + double fd_weight = fraction_done; double wu_weight = 1 - fd_weight; double x = fd_weight*frac_est + wu_weight*wu_est; #if 0