diff --git a/api/boinc_api.C b/api/boinc_api.C index bac0b313c9..1439cd0630 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -83,6 +83,8 @@ static volatile bool heartbeat_active; #ifdef _WIN32 static volatile int nrunning_ticks = 0; #endif +static double fpops_per_cpu_sec = 0; +static double fpops_cumulative = 0; #define TIMER_PERIOD 1 // period of worker-thread timer @@ -179,6 +181,14 @@ static bool update_app_progress( sprintf(buf, "%f\n", vm); strcat(msg_buf, buf); } + if (fpops_per_cpu_sec) { + sprintf(buf, "%f\n", fpops_per_cpu_sec); + strcat(msg_buf, buf); + } + if (fpops_cumulative) { + sprintf(buf, "%f\n", fpops_cumulative); + strcat(msg_buf, buf); + } return app_client_shm->shm->app_status.send_msg(msg_buf); } @@ -740,5 +750,12 @@ int boinc_upload_status(std::string& name) { return ERR_NOT_FOUND; } +void boinc_fpops_per_cpu_sec(double x) { + fpops_per_cpu_sec = x; +} + +void boinc_fpops_cumulative(double x) { + fpops_cumulative = x; +} const char *BOINC_RCSID_0fa0410386 = "$Id$"; diff --git a/api/boinc_api.h b/api/boinc_api.h index 7a15e51e37..dadfe57a86 100755 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -100,6 +100,8 @@ extern int boinc_get_init_data(APP_INIT_DATA&); extern int boinc_wu_cpu_time(double&); extern int boinc_upload_file(std::string& name); extern int boinc_upload_status(std::string& name); +extern void boinc_fpops_per_cpu_sec(double); +extern void boinc_fpops_cumulative(double); /////////// API ENDS HERE diff --git a/checkin_notes b/checkin_notes index 9c44db9562..ebdb8997e1 100755 --- a/checkin_notes +++ b/checkin_notes @@ -8377,3 +8377,34 @@ Janus 23 June 2005 user/ top_users.php +David 23 June 2005 + - Add new API calls so that optimized apps can claim credit more accurately: + + boinc_fpops_per_cpu_sec() + Report results of app-specific benchmarks + boinc_fpops_cumulative() + Report total FP operations so far in this result + + These are stored by the API library and passed to the core client + in status messages. + The core client stores them in the RESULT and sends them to server + - scheduling server: assign claimed credit based on + fpops_per_cpu_sec or fpops_cumulative if present + - remove compile warnings + + api/ + boinc_api.C,h + client/ + acct_mgr.C + client_state.h + client_types.C,h + cs_apps.C + gui_rpc_server.C + db/ + boinc_db.h + doc/ + api.php + sched/ + handle_request.C + sched_shmem.C + server_types.C diff --git a/client/acct_mgr.C b/client/acct_mgr.C index 583b29800e..6563ed097d 100644 --- a/client/acct_mgr.C +++ b/client/acct_mgr.C @@ -217,7 +217,6 @@ int ACCT_MGR_INFO::write_info() { int ACCT_MGR_INFO::init() { char buf[256]; - int retval=0; MIOFILE mf; FILE* p; diff --git a/client/client_state.h b/client/client_state.h index 559614f84c..6c4f398e64 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -244,7 +244,7 @@ private: int app_finished(ACTIVE_TASK&); void assign_results_to_projects(); bool schedule_largest_debt_project(double expected_pay_off); - bool schedule_earliest_deadline_result(double expected_pay_off); + bool schedule_earliest_deadline_result(); bool start_apps(); bool schedule_cpus(); bool handle_finished_apps(); diff --git a/client/client_types.C b/client/client_types.C index e5daa3dcff..99fd03ced5 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -1177,6 +1177,8 @@ void RESULT::clear() { stderr_out = ""; suspended_via_gui = false; aborted_via_gui = false; + fpops_per_cpu_sec = 0; + fpops_cumulative = 0; app = NULL; wup = NULL; project = NULL; @@ -1253,6 +1255,8 @@ int RESULT::parse_state(MIOFILE& in) { } continue; } + else if (parse_double(buf, "", fpops_per_cpu_sec)) continue; + else if (parse_double(buf, "", fpops_cumulative)) continue; else scope_messages.printf("RESULT::parse(): unrecognized: %s\n", buf); } return ERR_XML_PARSE; @@ -1274,6 +1278,16 @@ int RESULT::write(MIOFILE& out, bool to_server) { exit_status, state ); + if (fpops_per_cpu_sec) { + out.printf( + " %f\n", fpops_per_cpu_sec + ); + } + if (fpops_cumulative) { + out.printf( + " %f\n", fpops_cumulative + ); + } if (to_server) { out.printf( " %d\n", diff --git a/client/client_types.h b/client/client_types.h index b28dd46f4e..5eb0f53457 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -384,8 +384,10 @@ struct RESULT { bool got_server_ack; // we're received the ack for this result from the server double final_cpu_time; - int state; // state of this result: see lib/result_state.h - int exit_status; // return value from the application + double fpops_per_cpu_sec; // nonzero if reported by app + double fpops_cumulative; // nonzero if reported by app + int state; // state of this result: see lib/result_state.h + int exit_status; // return value from the application std::string stderr_out; // the concatenation of: // diff --git a/client/cs_apps.C b/client/cs_apps.C index 08fb7ed583..629e8954a9 100644 --- a/client/cs_apps.C +++ b/client/cs_apps.C @@ -344,7 +344,7 @@ bool CLIENT_STATE::schedule_largest_debt_project(double expected_pay_off) { // Schedule the active task with the earliest deadline // Return true iff a task was scheduled. // -bool CLIENT_STATE::schedule_earliest_deadline_result(double expected_pay_off) { +bool CLIENT_STATE::schedule_earliest_deadline_result() { PROJECT *best_project = NULL; RESULT *best_result = NULL; double earliest_deadline=0; @@ -569,7 +569,7 @@ bool CLIENT_STATE::schedule_cpus() { expected_pay_off = total_wall_cpu_time_this_period / ncpus; for (j=0; jflush() or close(). This lets you write output files and state files more or less atomically. +

Credit reporting

+

+By default, the credit assigned to a result is based on +the product of its total CPU time and +benchmarks run by the core client. +This can produce results that are too low if +the application uses processor-specific optimizations +not present in the core client, +is compiled with different compiler settings, +or uses a GPU or other non-CPU computing resource. +To handle such cases, the following functions can be used. +

+void boinc_fpops_per_cpu_second(double);
+
+This reports the results of an application-specific benchmark, +expressed as number of floating-point operations per CPU second. +
+void boinc_fpops_cumulative(double);
+
+This reports the total number of floating-point operations +since the start of the result. +It must be called just before boinc_finish(), +and optionally at intermediate points. +

Communicating with the core client

The core client GUI displays the percent done of workunits in progress. diff --git a/doc/build_system.php b/doc/build_system.php index 069d8bc616..7026956a31 100644 --- a/doc/build_system.php +++ b/doc/build_system.php @@ -28,7 +28,7 @@ To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. Example: to compile BOINC with strict compiler warnings, use

-./configure CXXFLAGS=\"-Wall -W -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common -Wnested-externs\"
+./configure CXXFLAGS=\"-Wall -W -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common \"
 

diff --git a/sched/handle_request.C b/sched/handle_request.C index e1d55110d1..f3f7fa5c2d 100644 --- a/sched/handle_request.C +++ b/sched/handle_request.C @@ -324,7 +324,6 @@ make_new_host: // if (strlen(sreq.cross_project_id)) { if (strcmp(sreq.cross_project_id, reply.user.cross_project_id)) { - DB_USER user; user.id = reply.user.id; escape_string(sreq.cross_project_id, sizeof(sreq.cross_project_id)); sprintf(buf, "cross_project_id='%s'", sreq.cross_project_id); @@ -335,14 +334,19 @@ make_new_host: return 0; } +#define COBBLESTONE_FACTOR 100.0 + // somewhat arbitrary formula for credit as a function of CPU time. // Could also include terms for RAM size, network speed etc. // static void compute_credit_rating(HOST& host) { - double cobblestone_factor = 100; host.credit_per_cpu_sec = (fabs(host.p_fpops)/1e9 + fabs(host.p_iops)/1e9) - * cobblestone_factor / (2 * SECONDS_PER_DAY); + * COBBLESTONE_FACTOR / (2 * SECONDS_PER_DAY); +} + +static double fpops_to_credit(double fpops) { + return (fpops/1e9)*COBBLESTONE_FACTOR/SECONDS_PER_DAY; } // modify host struct based on request. @@ -599,7 +603,13 @@ int handle_results(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& reply) { srip->cpu_time = rp->cpu_time; srip->exit_status = rp->exit_status; srip->app_version_num = rp->app_version_num; - srip->claimed_credit = rp->cpu_time * reply.host.credit_per_cpu_sec; + if (rp->fpops_cumulative) { + srip->claimed_credit = fpops_to_credit(rp->fpops_cumulative); + } else if (rp->fpops_per_cpu_sec) { + srip->claimed_credit = fpops_to_credit(rp->fpops_per_cpu_sec*rp->cpu_time); + } else { + srip->claimed_credit = rp->cpu_time * reply.host.credit_per_cpu_sec; + } #ifdef EINSTEIN_AT_HOME log_messages.printf(SCHED_MSG_LOG::DEBUG, "cpu %f cpcs %f, cc %f\n", srip->cpu_time, reply.host.credit_per_cpu_sec, srip->claimed_credit diff --git a/sched/sched_shmem.C b/sched/sched_shmem.C index 0cdf9075e5..1f6f630160 100644 --- a/sched/sched_shmem.C +++ b/sched/sched_shmem.C @@ -50,7 +50,7 @@ void SCHED_SHMEM::init() { nwu_results = MAX_WU_RESULTS; } -static int error_return(char* p) { +static int error_return(const char* p) { fprintf(stderr, "Error in structure: %s\n", p); return ERR_SCHED_SHMEM; } diff --git a/sched/server_types.C b/sched/server_types.C index a18b94be7a..92e8ed3115 100644 --- a/sched/server_types.C +++ b/sched/server_types.C @@ -620,6 +620,8 @@ int RESULT::parse_from_client(FILE* fin) { else if (parse_double(buf, "", cpu_time)) continue; else if (parse_int(buf, "", exit_status)) continue; else if (parse_int(buf, "", app_version_num)) continue; + else if (parse_double(buf, "", fpops_per_cpu_sec)) continue; + else if (parse_double(buf, "", fpops_cumulative)) continue; else if (match_tag(buf, "")) { safe_strcat(xml_doc_out, buf); while (fgets(buf, 256, fin)) {