From 290145dd966a7064007b775031218f0b1eb0ddff Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 21 Sep 2023 10:00:45 -0700 Subject: [PATCH 01/14] Plumbing for sporadic app feature. Not finished. --- api/boinc_api.cpp | 20 ++++++++++ api/boinc_api.h | 5 +++ client/Makefile.am | 1 + client/Makefile.linux | 2 + client/app.cpp | 2 + client/app.h | 2 + client/app_control.cpp | 12 +++++- client/app_test.cpp | 2 + client/client_state.cpp | 1 + client/client_state.h | 3 ++ client/client_types.cpp | 2 + client/client_types.h | 1 + lib/app_ipc.h | 32 ++++++---------- lib/cc_config.cpp | 3 ++ lib/cc_config.h | 1 + lib/common_defs.h | 20 ++++++++++ samples/sporadic/Makefile | 8 ++++ samples/sporadic/sporadic.cpp | 71 +++++++++++++++++++++++++++++++++++ 18 files changed, 167 insertions(+), 21 deletions(-) create mode 100644 samples/sporadic/Makefile create mode 100644 samples/sporadic/sporadic.cpp diff --git a/api/boinc_api.cpp b/api/boinc_api.cpp index ace3dba97d3..191a2274fc4 100644 --- a/api/boinc_api.cpp +++ b/api/boinc_api.cpp @@ -194,6 +194,7 @@ char remote_desktop_addr[256]; bool send_remote_desktop_addr = false; int app_min_checkpoint_period = 0; // min checkpoint period requested by app +SPORADIC_AC_STATE ac_state; #define TIMER_PERIOD 0.1 // Sleep interval for timer thread; @@ -434,6 +435,10 @@ static bool update_app_progress(double cpu_t, double cp_cpu_t) { snprintf(buf, sizeof(buf), "%f\n", bytes_received); strlcat(msg_buf, buf, sizeof(msg_buf)); } + if (ac_state) { + sprintf(buf, "%d\n", ac_state); + strlcat(msg_buf, buf, sizeof(msg_buf)); + } #ifdef MSGS_FROM_FILE if (fout) { fputs(msg_buf, fout); @@ -450,6 +455,7 @@ static void handle_heartbeat_msg() { char buf[MSG_CHANNEL_SIZE]; double dtemp; bool btemp; + int i; if (!app_client_shm->shm->heartbeat.get_msg(buf)) { return; @@ -467,6 +473,9 @@ static void handle_heartbeat_msg() { if (parse_bool(buf, "suspend_network", btemp)) { boinc_status.network_suspended = btemp; } + if (parse_int(buf, "sporadic_ca", i)) { + boinc_status.ca_state = (SPORADIC_CA_STATE)i; + } } // called in timer thread @@ -714,6 +723,7 @@ int boinc_init_options_general(BOINC_OPTIONS& opt) { } int boinc_get_status(BOINC_STATUS *s) { + // can just do a struct copy?? s->no_heartbeat = boinc_status.no_heartbeat; s->suspended = boinc_status.suspended; s->quit_request = boinc_status.quit_request; @@ -722,6 +732,7 @@ int boinc_get_status(BOINC_STATUS *s) { s->working_set_size = boinc_status.working_set_size; s->max_working_set_size = boinc_status.max_working_set_size; s->network_suspended = boinc_status.network_suspended; + s->ca_state = boinc_status.ca_state; return 0; } @@ -1697,3 +1708,12 @@ void boinc_remote_desktop_addr(char* addr) { strlcpy(remote_desktop_addr, addr, sizeof(remote_desktop_addr)); send_remote_desktop_addr = true; } + +void boinc_sporadic_set_ac_state(SPORADIC_AC_STATE a) { + ac_state = a; +} + +SPORADIC_CA_STATE boinc_sporadic_get_ca_state() { + return boinc_status.ca_state; +} + diff --git a/api/boinc_api.h b/api/boinc_api.h index 3924bad1bfc..1218de36642 100644 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -63,6 +63,8 @@ typedef struct BOINC_OPTIONS { // set this if application creates subprocesses. } BOINC_OPTIONS; +// info passed from client to app in heartbeat message +// typedef struct BOINC_STATUS { int no_heartbeat; int suspended; @@ -72,6 +74,7 @@ typedef struct BOINC_STATUS { double working_set_size; double max_working_set_size; int network_suspended; + SPORADIC_CA_STATE ca_state; } BOINC_STATUS; extern volatile BOINC_STATUS boinc_status; @@ -143,6 +146,8 @@ extern int boinc_temporary_exit( extern int boinc_finish_message( int status, const char* message, bool is_notice ); +extern void boinc_sporadic_set_ac_state(SPORADIC_AC_STATE); +extern SPORADIC_CA_STATE boinc_sporadic_get_ca_state(); /////////// API ENDS HERE diff --git a/client/Makefile.am b/client/Makefile.am index e583aa24ad1..f6cb71469d2 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -58,6 +58,7 @@ boinc_client_SOURCES = \ cs_prefs.cpp \ cs_proxy.cpp \ cs_scheduler.cpp \ + cs_sporadic.cpp \ cs_statefile.cpp \ cs_trickle.cpp \ current_version.cpp \ diff --git a/client/Makefile.linux b/client/Makefile.linux index 7f0461d74e6..bfac0c26e31 100644 --- a/client/Makefile.linux +++ b/client/Makefile.linux @@ -38,6 +38,7 @@ BOINC_OBJ = \ cs_prefs.o \ cs_proxy.o \ cs_scheduler.o \ + cs_sporadic.o \ cs_statefile.o \ cs_trickle.o \ current_version.o \ @@ -98,6 +99,7 @@ SRC = \ cs_proxy.cpp \ cs_scheduler.cpp \ cs_statefile.cpp \ + cs_sporadic.cpp \ cs_trickle.cpp \ current_version.cpp \ dhrystone.cpp \ diff --git a/client/app.cpp b/client/app.cpp index 28184ba3589..0bcb1a734cf 100644 --- a/client/app.cpp +++ b/client/app.cpp @@ -150,6 +150,8 @@ ACTIVE_TASK::ACTIVE_TASK() { safe_strcpy(remote_desktop_addr, ""); async_copy = NULL; finish_file_time = 0; + sporadic_ca_state = CA_NONE; + sporadic_ac_state = AC_NONE; } bool ACTIVE_TASK::process_exists() { diff --git a/client/app.h b/client/app.h index e8f881794d0..efc8a2ebc0c 100644 --- a/client/app.h +++ b/client/app.h @@ -184,6 +184,8 @@ struct ACTIVE_TASK { // Used to kill apps that hang after writing finished file int graphics_pid; // PID of running graphics app (Mac) + SPORADIC_CA_STATE sporadic_ca_state; + SPORADIC_AC_STATE sporadic_ac_state; void set_task_state(int, const char*); inline int task_state() { diff --git a/client/app_control.cpp b/client/app_control.cpp index 6d6d6861796..172514290c5 100644 --- a/client/app_control.cpp +++ b/client/app_control.cpp @@ -727,6 +727,13 @@ void ACTIVE_TASK_SET::send_heartbeats() { if (gstate.network_suspended) { safe_strcat(buf, ""); } + if (atp->sporadic_ca_state) { + char buf2[256]; + sprintf(buf2, "%d", + atp->sporadic_ca_state + ); + safe_strcat(buf, buf2); + } bool sent = atp->app_client_shm.shm->heartbeat.send_msg(buf); if (log_flags.heartbeat_debug) { if (sent) { @@ -1390,7 +1397,7 @@ void ACTIVE_TASK::send_network_available() { bool ACTIVE_TASK::get_app_status_msg() { char msg_buf[MSG_CHANNEL_SIZE]; double fd; - int other_pid; + int other_pid, i; double dtemp; static double last_msg_time=0; @@ -1460,6 +1467,9 @@ bool ACTIVE_TASK::get_app_status_msg() { other_pids.clear(); other_pids.push_back(other_pid); } + if (parse_int(msg_buf, "", i)) { + sporadic_ca_state = (SPORADIC_CA_STATE)i; + } if (current_cpu_time < 0) { msg_printf(result->project, MSG_INFO, "app reporting negative CPU: %f", current_cpu_time diff --git a/client/app_test.cpp b/client/app_test.cpp index 5c899ee6cb8..15be783c2ba 100644 --- a/client/app_test.cpp +++ b/client/app_test.cpp @@ -37,6 +37,8 @@ void CLIENT_STATE::app_test_init() { strcpy(app->name, "test app"); strcpy(app->user_friendly_name, "test app"); app->project = proj; + // can put other stuff here like + // app->sporadic = true; apps.push_back(app); FILE_INFO *fip = new FILE_INFO; diff --git a/client/client_state.cpp b/client/client_state.cpp index 0a32d53941e..e61c23372a4 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -949,6 +949,7 @@ void CLIENT_STATE::do_io_or_sleep(double max_time) { // possibly triggering state transitions. // Returns true if something happened // (in which case should call this again immediately) +// Called every POLL_INTERVAL (1 sec) // bool CLIENT_STATE::poll_slow_events() { int actions = 0, retval; diff --git a/client/client_state.h b/client/client_state.h index 44f62df8d75..74ab22f9626 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -460,6 +460,9 @@ struct CLIENT_STATE { bool had_or_requested_work; bool scheduler_rpc_poll(); +// --------------- cs_sporadic.cpp: + void sporadic_poll(); + // --------------- cs_statefile.cpp: void set_client_state_dirty(const char*); int parse_state_file(); diff --git a/client/client_types.cpp b/client/client_types.cpp index afe9aa9d143..f3704bcfc3b 100644 --- a/client/client_types.cpp +++ b/client/client_types.cpp @@ -142,6 +142,7 @@ int APP::parse(XML_PARSER& xp) { safe_strcpy(user_friendly_name, ""); project = NULL; non_cpu_intensive = false; + sporadic = false; while (!xp.get_tag()) { if (xp.match_tag("/app")) { if (!strlen(user_friendly_name)) { @@ -152,6 +153,7 @@ int APP::parse(XML_PARSER& xp) { if (xp.parse_str("name", name, sizeof(name))) continue; if (xp.parse_str("user_friendly_name", user_friendly_name, sizeof(user_friendly_name))) continue; if (xp.parse_bool("non_cpu_intensive", non_cpu_intensive)) continue; + if (xp.parse_bool("sporadic", sporadic)) continue; if (xp.parse_bool("fraction_done_exact", fraction_done_exact)) continue; #ifdef SIM if (xp.parse_double("latency_bound", latency_bound)) continue; diff --git a/client/client_types.h b/client/client_types.h index 567618178c6..7a444078170 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -268,6 +268,7 @@ struct APP { char name[256]; char user_friendly_name[256]; bool non_cpu_intensive; + bool sporadic; bool fraction_done_exact; PROJECT* project; bool report_results_immediately; diff --git a/lib/app_ipc.h b/lib/app_ipc.h index 54b10dc3c05..2ead2168f75 100644 --- a/lib/app_ipc.h +++ b/lib/app_ipc.h @@ -46,7 +46,7 @@ // Shared memory is a set of MSG_CHANNELs. // First byte of a channel is nonzero if -// the channel contains an unread data. +// the channel contains unread data. // This is set by the sender and cleared by the receiver. // The sender doesn't write if the flag is set. // Remaining 1023 bytes contain data. @@ -55,49 +55,41 @@ struct MSG_CHANNEL { char buf[MSG_CHANNEL_SIZE]; - bool get_msg(char*); // returns a message and clears pending flag + bool get_msg(char*); + // returns a message and clears pending flag inline bool has_msg() { return buf[0]?true:false; } - bool send_msg(const char*); // if there is not a message in the segment, - // writes specified message and sets pending flag + bool send_msg(const char*); + // if there is not a message in the segment, + // writes specified message and sets pending flag void send_msg_overwrite(const char*); - // write message, overwriting any msg already there + // write message, overwriting any msg already there }; struct SHARED_MEM { + // don't change the order of these! + // See https://github.com/BOINC/boinc/wiki/API-Implementation + // for message formats and details + // MSG_CHANNEL process_control_request; // core->app - // - // - // MSG_CHANNEL process_control_reply; // app->core + // not used MSG_CHANNEL graphics_request; // core->app // not currently used MSG_CHANNEL graphics_reply; // app->core - // - // MSG_CHANNEL heartbeat; // core->app - // sent every second, even while app is suspended - // app's current working set size - // max working set size MSG_CHANNEL app_status; // app->core - // status message every second, of the form - // ... - // ... - // ... - // ... MSG_CHANNEL trickle_up; // app->core - // MSG_CHANNEL trickle_down; // core->app - // }; // MSG_QUEUE provides a queuing mechanism for shared-mem messages diff --git a/lib/cc_config.cpp b/lib/cc_config.cpp index 38d5b6e7998..7be77f398aa 100644 --- a/lib/cc_config.cpp +++ b/lib/cc_config.cpp @@ -88,6 +88,7 @@ int LOG_FLAGS::parse(XML_PARSER& xp) { if (xp.parse_bool("sched_op_debug", sched_op_debug)) continue; if (xp.parse_bool("scrsave_debug", scrsave_debug)) continue; if (xp.parse_bool("slot_debug", slot_debug)) continue; + if (xp.parse_bool("sporadic_debug", sporadic_debug)) continue; if (xp.parse_bool("state_debug", state_debug)) continue; if (xp.parse_bool("statefile_debug", statefile_debug)) continue; if (xp.parse_bool("suspend_debug", suspend_debug)) continue; @@ -138,6 +139,7 @@ int LOG_FLAGS::write(MIOFILE& out) { " %d\n" " %d\n" " %d\n" + " %d\n" " %d\n" " %d\n" " %d\n" @@ -181,6 +183,7 @@ int LOG_FLAGS::write(MIOFILE& out) { sched_op_debug ? 1 : 0, scrsave_debug ? 1 : 0, slot_debug ? 1 : 0, + sporadic_debug ? 1 : 0, state_debug ? 1 : 0, statefile_debug ? 1 : 0, suspend_debug ? 1 : 0, diff --git a/lib/cc_config.h b/lib/cc_config.h index 88c62d50e53..9979c628bea 100644 --- a/lib/cc_config.h +++ b/lib/cc_config.h @@ -102,6 +102,7 @@ struct LOG_FLAGS { bool scrsave_debug; bool slot_debug; // allocation of slots + bool sporadic_debug; bool state_debug; // print textual summary of CLIENT_STATE initially // and after each scheduler RPC and garbage collect diff --git a/lib/common_defs.h b/lib/common_defs.h index f93dc42ea75..2bcce7c5845 100644 --- a/lib/common_defs.h +++ b/lib/common_defs.h @@ -170,6 +170,26 @@ enum BATTERY_STATE { BATTERY_STATE_OVERHEATED }; +// states for sporadic apps +// +// client state +enum SPORADIC_CA_STATE { + CA_NONE = 0, + CA_DONT_COMPUTE = 1, + // computing suspended (CPU and perhaps GPU) or other project have priority + CA_COULD_COMPUTE = 2, + // not computing, but could + CA_COMPUTING = 3 + // go ahead and compute +}; + +// app state +enum SPORADIC_AC_STATE { + AC_NONE = 0, + AC_DONT_WANT_COMPUTE = 1, + AC_WANT_COMPUTE = 2 +}; + // Values of RESULT::state in client. // THESE MUST BE IN NUMERICAL ORDER // (because of the > comparison in RESULT::computing_done()) diff --git a/samples/sporadic/Makefile b/samples/sporadic/Makefile new file mode 100644 index 00000000000..4d6eff1ec12 --- /dev/null +++ b/samples/sporadic/Makefile @@ -0,0 +1,8 @@ +all: sporadic + +INC_DIRS = -I ../../api -I ../../lib +LIB_DIRS = -L ../../api -L ../../lib +CXX = g++ $(INC_DIRS) + +sporadic: sporadic.cpp + $(CXX) $(LIB_DIRS) sporadic.cpp -lboinc_api -lboinc -lpthread -o sporadic diff --git a/samples/sporadic/sporadic.cpp b/samples/sporadic/sporadic.cpp new file mode 100644 index 00000000000..6ccca82b223 --- /dev/null +++ b/samples/sporadic/sporadic.cpp @@ -0,0 +1,71 @@ +// test sporadic app +// +// loop +// wait for NWAIT secs +// wait for could compute +// ask to compute (simulate getting a request) +// when OK, compute for NCOMP secs +// suspend as needed +// +// computing is embedded in loop. +// in a real app you'd want to use threads + +#define NWAIT 10 +#define NCOMP 30 + +#include "boinc_api.h" +#include "util.h" +#include "common_defs.h" + +void boinc_sporadic_set_ac_state(AC_STATE); +CA_STATE boinc_sporadic_get_ca_state(); + +void print_state() { +} + +void compute_one_sec() { + double start = dtime(); + while (1) { + double x = 0; + for (int i=0; i<1e9; i++) { + x += 1; + } + if (dtime() > start+1) break; + } +} + +int main(int, char**) { + boinc_init(); + CA_STATE ca_state; + AC_STATE ac_state; + while (true) { + // wait for a bit + ac_state = AC_DONT_WANT_COMPUTE; + boinc_sporadic_set_ac_state(ac_state); + for (int i=0; i Date: Wed, 27 Sep 2023 15:53:33 -0700 Subject: [PATCH 02/14] Intermediate checkin. Simple test cases now work. - call sporadic init and poll functions - add sporadic_debug log flag - finish sporadic test app (samples/sporadic/sporadic.cpp) - sporadic jobs are always run (like NCI) - projects can now have a mix of regular, non CPU intensive, and sporadic apps. This mix can change over time. Because of this, there is longer a project-wide NCI flag. Projects have to tag individual apps as NCI. I don't think this affects any current projects. - fix potential timing problem in client/app comm by introducing 2.5 sec 'ignore_until' period - API: fix bug in parsing hearbeats - Add member functions of RESULT, ACTIVE_TASK etc. so you can get APP attributes like cpu_intensive, sporadic etc. without traversing pointers - --app_test feature: put init_data.xml in slots/app_test, otherwise app will run in standalone mode --- api/boinc_api.cpp | 2 +- client/app.cpp | 1 + client/app.h | 14 ++++++++++++++ client/app_control.cpp | 14 +++++++------- client/app_start.cpp | 10 +++++++--- client/app_test.cpp | 6 +++++- client/client_state.cpp | 9 +++++++++ client/client_state.h | 2 ++ client/client_types.cpp | 4 ++++ client/cpu_sched.cpp | 15 +++++++-------- client/cs_scheduler.cpp | 1 + client/log_flags.cpp | 1 + client/project.cpp | 7 ++----- client/project.h | 2 +- client/result.cpp | 4 +++- client/result.h | 10 +++++++--- client/rr_sim.cpp | 2 +- client/scheduler_op.cpp | 4 ---- lib/Makefile.linux | 3 ++- samples/sporadic/sporadic.cpp | 25 ++++++++++++++++++------- 20 files changed, 93 insertions(+), 43 deletions(-) diff --git a/api/boinc_api.cpp b/api/boinc_api.cpp index 191a2274fc4..5cded0cd01f 100644 --- a/api/boinc_api.cpp +++ b/api/boinc_api.cpp @@ -473,7 +473,7 @@ static void handle_heartbeat_msg() { if (parse_bool(buf, "suspend_network", btemp)) { boinc_status.network_suspended = btemp; } - if (parse_int(buf, "sporadic_ca", i)) { + if (parse_int(buf, "", i)) { boinc_status.ca_state = (SPORADIC_CA_STATE)i; } } diff --git a/client/app.cpp b/client/app.cpp index 0bcb1a734cf..a0254c277f3 100644 --- a/client/app.cpp +++ b/client/app.cpp @@ -152,6 +152,7 @@ ACTIVE_TASK::ACTIVE_TASK() { finish_file_time = 0; sporadic_ca_state = CA_NONE; sporadic_ac_state = AC_NONE; + sporadic_ignore_until = 0; } bool ACTIVE_TASK::process_exists() { diff --git a/client/app.h b/client/app.h index efc8a2ebc0c..1999acaeb11 100644 --- a/client/app.h +++ b/client/app.h @@ -28,6 +28,7 @@ #include "procinfo.h" #include "client_types.h" +#include "result.h" // values for preempt_type (see ACTIVE_TASK::preempt()) // @@ -186,11 +187,24 @@ struct ACTIVE_TASK { // PID of running graphics app (Mac) SPORADIC_CA_STATE sporadic_ca_state; SPORADIC_AC_STATE sporadic_ac_state; + double sporadic_ignore_until; void set_task_state(int, const char*); inline int task_state() { return _task_state; } + inline bool sporadic() { + return wup->app->sporadic; + } + inline bool non_cpu_intensive() { + return result->app->non_cpu_intensive; + } + inline bool always_run() { + return sporadic() || non_cpu_intensive(); + } + inline bool dont_throttle() { + return result->dont_throttle(); + } int request_reread_prefs(); int request_reread_app_info(); int link_user_files(); diff --git a/client/app_control.cpp b/client/app_control.cpp index 172514290c5..99b9349d619 100644 --- a/client/app_control.cpp +++ b/client/app_control.cpp @@ -727,7 +727,7 @@ void ACTIVE_TASK_SET::send_heartbeats() { if (gstate.network_suspended) { safe_strcat(buf, ""); } - if (atp->sporadic_ca_state) { + if (atp->sporadic_ca_state != CA_NONE) { char buf2[256]; sprintf(buf2, "%d", atp->sporadic_ca_state @@ -896,7 +896,7 @@ bool ACTIVE_TASK_SET::check_rsc_limits_exceeded() { for (i=0; itask_state() != PROCESS_EXECUTING) continue; - if (!atp->result->non_cpu_intensive() && (atp->elapsed_time > atp->max_elapsed_time)) { + if (!atp->always_run() && (atp->elapsed_time > atp->max_elapsed_time)) { snprintf(buf, sizeof(buf), "exceeded elapsed time limit %.2f (%.2fG/%.2fG)", atp->max_elapsed_time, atp->result->wup->rsc_fpops_bound/1e9, @@ -950,7 +950,7 @@ bool ACTIVE_TASK_SET::check_rsc_limits_exceeded() { // don't count RAM usage of non-CPU-intensive jobs // - if (!atp->result->non_cpu_intensive()) { + if (!atp->non_cpu_intensive()) { ram_left -= atp->procinfo.working_set_size_smoothed; } } @@ -1213,7 +1213,7 @@ void ACTIVE_TASK_SET::suspend_all(int reason) { // special cases for non-CPU-intensive apps // - if (atp->result->non_cpu_intensive()) { + if (atp->non_cpu_intensive()) { if (cc_config.dont_suspend_nci) { continue; } @@ -1225,7 +1225,7 @@ void ACTIVE_TASK_SET::suspend_all(int reason) { // handle CPU throttling separately // if (reason == SUSPEND_REASON_CPU_THROTTLE) { - if (atp->result->dont_throttle()) continue; + if (atp->dont_throttle()) continue; atp->preempt(REMOVE_NEVER, reason); continue; } @@ -1253,7 +1253,7 @@ void ACTIVE_TASK_SET::suspend_all(int reason) { // which uses a lot of CPU. // Avoid going into a preemption loop. // - if (atp->result->non_cpu_intensive()) break; + if (atp->always_run()) break; atp->preempt(REMOVE_NEVER); break; case SUSPEND_REASON_BATTERY_OVERHEATED: @@ -1468,7 +1468,7 @@ bool ACTIVE_TASK::get_app_status_msg() { other_pids.push_back(other_pid); } if (parse_int(msg_buf, "", i)) { - sporadic_ca_state = (SPORADIC_CA_STATE)i; + sporadic_ac_state = (SPORADIC_AC_STATE)i; } if (current_cpu_time < 0) { msg_printf(result->project, MSG_INFO, diff --git a/client/app_start.cpp b/client/app_start.cpp index b0c34a601ee..d6b9073b35d 100644 --- a/client/app_start.cpp +++ b/client/app_start.cpp @@ -556,6 +556,12 @@ int ACTIVE_TASK::start(bool test) { return 0; } + // use special slot for test app + // + if (wup->project->app_test) { + strcpy(slot_dir, "slots/app_test"); + } + // run it at above idle priority if it // - uses coprocs // - uses less than one CPU @@ -691,14 +697,12 @@ int ACTIVE_TASK::start(bool test) { exit(0); } - // use special slot and exec path for test app + // use special exec path for test app // if (wup->project->app_test) { - strcpy(slot_dir, "slots/app_test"); strcpy(exec_path, gstate.app_test_file.c_str()); } - #ifdef _WIN32 PROCESS_INFORMATION process_info; STARTUPINFO startup_info; diff --git a/client/app_test.cpp b/client/app_test.cpp index 15be783c2ba..229435981d5 100644 --- a/client/app_test.cpp +++ b/client/app_test.cpp @@ -31,6 +31,7 @@ void CLIENT_STATE::app_test_init() { strcpy(proj->master_url, "test_project_url"); strcpy(proj->_project_dir, "."); proj->app_test = true; + proj->non_cpu_intensive = false; projects.push_back(proj); APP *app = new APP; @@ -38,7 +39,8 @@ void CLIENT_STATE::app_test_init() { strcpy(app->user_friendly_name, "test app"); app->project = proj; // can put other stuff here like - // app->sporadic = true; + app->sporadic = true; + have_sporadic = true; apps.push_back(app); FILE_INFO *fip = new FILE_INFO; @@ -58,6 +60,8 @@ void CLIENT_STATE::app_test_init() { av->app = app; av->project = proj; av->app_files.push_back(*fref); + // can put other stuff here like + av->avg_ncpus = 1; app_versions.push_back(av); WORKUNIT *wu = new WORKUNIT; diff --git a/client/client_state.cpp b/client/client_state.cpp index e61c23372a4..92105270828 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -186,6 +186,7 @@ CLIENT_STATE::CLIENT_STATE() #ifdef _WIN32 have_sysmon_msg = false; #endif + have_sporadic = false; } void CLIENT_STATE::show_host_info() { @@ -858,6 +859,8 @@ int CLIENT_STATE::init() { client_thread_mutex.lock(); throttle_thread.run(throttler, NULL); + sporadic_init(); + initialized = true; return 0; } @@ -1163,6 +1166,9 @@ bool CLIENT_STATE::poll_slow_events() { if (!network_suspended) { POLL_ACTION(scheduler_rpc , scheduler_rpc_poll ); } + if (have_sporadic) { + sporadic_poll(); + } retval = write_state_file_if_needed(); if (retval) { msg_printf(NULL, MSG_INTERNAL_ERROR, @@ -1270,6 +1276,9 @@ FILE_INFO* CLIENT_STATE::lookup_file_info(PROJECT* p, const char* name) { int CLIENT_STATE::link_app(PROJECT* p, APP* app) { if (lookup_app(p, app->name)) return ERR_NOT_UNIQUE; app->project = p; + if (!app->non_cpu_intensive) { + p->non_cpu_intensive = false; + } return 0; } diff --git a/client/client_state.h b/client/client_state.h index 74ab22f9626..7b61a8b40ad 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -461,7 +461,9 @@ struct CLIENT_STATE { bool scheduler_rpc_poll(); // --------------- cs_sporadic.cpp: + bool have_sporadic; void sporadic_poll(); + void sporadic_init(); // --------------- cs_statefile.cpp: void set_client_state_dirty(const char*); diff --git a/client/client_types.cpp b/client/client_types.cpp index f3704bcfc3b..ce21fab4dcf 100644 --- a/client/client_types.cpp +++ b/client/client_types.cpp @@ -155,6 +155,10 @@ int APP::parse(XML_PARSER& xp) { if (xp.parse_bool("non_cpu_intensive", non_cpu_intensive)) continue; if (xp.parse_bool("sporadic", sporadic)) continue; if (xp.parse_bool("fraction_done_exact", fraction_done_exact)) continue; + if (xp.parse_bool("sporadic", sporadic)) { + if (sporadic) gstate.have_sporadic = true; + continue; + } #ifdef SIM if (xp.parse_double("latency_bound", latency_bound)) continue; if (xp.parse_double("fpops_est", fpops_est)) continue; diff --git a/client/cpu_sched.cpp b/client/cpu_sched.cpp index 8fcacee969c..390b5b6ad2e 100644 --- a/client/cpu_sched.cpp +++ b/client/cpu_sched.cpp @@ -346,6 +346,7 @@ void CLIENT_STATE::assign_results_to_projects() { // for (i=0; ialways_run()) continue; if (!atp->runnable()) continue; rp = atp->result; if (rp->already_selected) continue; @@ -410,7 +411,6 @@ RESULT* CLIENT_STATE::highest_prio_project_best_result() { for (i=0; inext_runnable_result) continue; - if (p->non_cpu_intensive) continue; if (first || p->sched_priority > best_prio) { first = false; best_project = p; @@ -447,7 +447,7 @@ RESULT* first_coproc_result(int rsc_type) { //msg_printf(rp->project, MSG_INFO, "not runnable: %s", rp->name); continue; } - if (rp->non_cpu_intensive()) continue; + if (rp->always_run()) continue; if (rp->already_selected) continue; prio = rp->project->sched_priority; if (!best) { @@ -500,7 +500,7 @@ static RESULT* earliest_deadline_result(int rsc_type) { if (rp->resource_type() != rsc_type) continue; if (rp->already_selected) continue; if (!rp->runnable()) continue; - if (rp->non_cpu_intensive()) continue; + if (rp->always_run()) continue; PROJECT* p = rp->project; // Skip this job if the project's deadline-miss count is zero. @@ -740,8 +740,7 @@ void CLIENT_STATE::adjust_rec() { for (i=0; ischeduler_state != CPU_SCHED_SCHEDULED) continue; - PROJECT* p = atp->result->project; - if (p->non_cpu_intensive) continue; + if (atp->non_cpu_intensive()) continue; work_fetch.accumulate_inst_sec(atp, elapsed_time); } @@ -1113,7 +1112,7 @@ void CLIENT_STATE::append_unfinished_time_slice(vector &run_list) { atp->overdue_checkpoint = false; if (!atp->result->runnable()) continue; if (atp->result->uses_gpu() && gpu_suspend_reason) continue; - if (atp->result->non_cpu_intensive()) continue; + if (atp->result->always_run()) continue; if (atp->scheduler_state != CPU_SCHED_SCHEDULED) continue; if (finished_time_slice(atp)) continue; atp->result->unfinished_time_slice = true; @@ -1212,11 +1211,11 @@ bool CLIENT_STATE::enforce_run_list(vector& run_list) { ); } - // schedule non-CPU-intensive tasks, + // schedule non-CPU-intensive and sporadic tasks // for (i=0; inon_cpu_intensive() && rp->runnable()) { + if (rp->always_run() && rp->runnable()) { atp = get_task(rp); if (!atp) { msg_printf(rp->project, MSG_INTERNAL_ERROR, diff --git a/client/cs_scheduler.cpp b/client/cs_scheduler.cpp index 0cb894a4371..22429489453 100644 --- a/client/cs_scheduler.cpp +++ b/client/cs_scheduler.cpp @@ -800,6 +800,7 @@ int CLIENT_STATE::handle_scheduler_reply( // safe_strcpy(app->user_friendly_name, checked_app.user_friendly_name); app->non_cpu_intensive = checked_app.non_cpu_intensive; + app->sporadic = checked_app.sporadic; app->fraction_done_exact = checked_app.fraction_done_exact; } else { app = new APP; diff --git a/client/log_flags.cpp b/client/log_flags.cpp index 842d6a4f283..11cc2712fcd 100644 --- a/client/log_flags.cpp +++ b/client/log_flags.cpp @@ -96,6 +96,7 @@ void LOG_FLAGS::show() { show_flag(buf, sizeof(buf), sched_op_debug, "sched_op_debug"); show_flag(buf, sizeof(buf), scrsave_debug, "scrsave_debug"); show_flag(buf, sizeof(buf), slot_debug, "slot_debug"); + show_flag(buf, sizeof(buf), sporadic_debug, "sporadic_debug"); show_flag(buf, sizeof(buf), state_debug, "state_debug"); show_flag(buf, sizeof(buf), statefile_debug, "statefile_debug"); show_flag(buf, sizeof(buf), task_debug, "task_debug"); diff --git a/client/project.cpp b/client/project.cpp index e83727e77de..5000d5813f4 100644 --- a/client/project.cpp +++ b/client/project.cpp @@ -86,7 +86,7 @@ void PROJECT::init() { disk_usage = 0.0; disk_share = 0.0; anonymous_platform = false; - non_cpu_intensive = false; + non_cpu_intensive = true; // true until link a non-NCI app report_results_immediately = false; pwf.reset(this); send_time_stats_log = 0; @@ -245,7 +245,6 @@ int PROJECT::parse_state(XML_PARSER& xp) { if (xp.parse_int("send_job_log", send_job_log)) continue; if (xp.parse_bool("send_full_workload", send_full_workload)) continue; if (xp.parse_bool("dont_use_dcf", dont_use_dcf)) continue; - if (xp.parse_bool("non_cpu_intensive", non_cpu_intensive)) continue; if (xp.parse_bool("suspended_via_gui", suspended_via_gui)) continue; if (xp.parse_bool("dont_request_more_work", dont_request_more_work)) continue; if (xp.parse_bool("detach_when_done", detach_when_done)) continue; @@ -422,7 +421,7 @@ int PROJECT::write_state(MIOFILE& out, bool gui_rpc) { " %d\n" " %f\n" " %f\n" - "%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s", master_url, project_name, symstore, @@ -465,7 +464,6 @@ int PROJECT::write_state(MIOFILE& out, bool gui_rpc) { trickle_up_pending?" \n":"", send_full_workload?" \n":"", dont_use_dcf?" \n":"", - non_cpu_intensive?" \n":"", suspended_via_gui?" \n":"", dont_request_more_work?" \n":"", detach_when_done?" \n":"", @@ -606,7 +604,6 @@ void PROJECT::copy_state_fields(PROJECT& p) { dont_use_dcf = p.dont_use_dcf; send_time_stats_log = p.send_time_stats_log; send_job_log = p.send_job_log; - non_cpu_intensive = p.non_cpu_intensive; suspended_via_gui = p.suspended_via_gui; dont_request_more_work = p.dont_request_more_work; detach_when_done = p.detach_when_done; diff --git a/client/project.h b/client/project.h index 9b8bc3c5503..bfe9d982f9b 100644 --- a/client/project.h +++ b/client/project.h @@ -169,7 +169,7 @@ struct PROJECT : PROJ_AM { // use those apps rather then getting from server bool non_cpu_intensive; // All this project's apps are non-CPU-intensive. - // Apps can also be individually marked as NCI + // (determined dynamically) bool use_symlinks; bool report_results_immediately; bool sched_req_no_work[MAX_RSC]; diff --git a/client/result.cpp b/client/result.cpp index c5f4bd57291..0a780872d4f 100644 --- a/client/result.cpp +++ b/client/result.cpp @@ -651,7 +651,8 @@ double RESULT::estimated_runtime() { double RESULT::estimated_runtime_remaining() { if (computing_done()) return 0; ACTIVE_TASK* atp = gstate.lookup_active_task_by_result(this); - if (app->non_cpu_intensive) { + if (non_cpu_intensive()) { + // the following is questionable if (atp && atp->fraction_done>0) { double est_dur = atp->fraction_done_elapsed_time / atp->fraction_done; double x = est_dur - atp->elapsed_time; @@ -660,6 +661,7 @@ double RESULT::estimated_runtime_remaining() { } return 0; } + if (sporadic()) return 0; if (atp) { #ifdef SIM diff --git a/client/result.h b/client/result.h index 632394b35fd..c712a2bcaee 100644 --- a/client/result.h +++ b/client/result.h @@ -156,9 +156,13 @@ struct RESULT { return avp->gpu_usage.rsc_type; } inline bool non_cpu_intensive() { - if (project->non_cpu_intensive) return true; - if (app->non_cpu_intensive) return true; - return false; + return app->non_cpu_intensive; + } + inline bool sporadic() { + return app->sporadic; + } + inline bool always_run() { + return non_cpu_intensive() || sporadic(); } inline bool dont_throttle() { if (non_cpu_intensive()) return true; diff --git a/client/rr_sim.cpp b/client/rr_sim.cpp index a7fe512cf13..80d8549052f 100644 --- a/client/rr_sim.cpp +++ b/client/rr_sim.cpp @@ -192,7 +192,7 @@ void RR_SIM::init_pending_lists() { rp->already_selected = false; if (!rp->nearly_runnable()) continue; if (rp->some_download_stalled()) continue; - if (rp->project->non_cpu_intensive) continue; + if (rp->always_run()) continue; rp->rrsim_flops_left = rp->estimated_flops_remaining(); //if (rp->rrsim_flops_left <= 0) continue; diff --git a/client/scheduler_op.cpp b/client/scheduler_op.cpp index 657c470b148..be87864e730 100644 --- a/client/scheduler_op.cpp +++ b/client/scheduler_op.cpp @@ -590,7 +590,6 @@ int SCHEDULER_REPLY::parse(FILE* in, PROJECT* project) { MIOFILE mf; XML_PARSER xp(&mf); string delete_file_name; - bool non_cpu_intensive = false; bool ended = false; mf.init_file(in); @@ -652,7 +651,6 @@ int SCHEDULER_REPLY::parse(FILE* in, PROJECT* project) { // boolean project attributes. // If the scheduler reply didn't specify them, they're not set. // - project->non_cpu_intensive = non_cpu_intensive; project->ended = ended; return 0; } @@ -857,8 +855,6 @@ int SCHEDULER_REPLY::parse(FILE* in, PROJECT* project) { ); } continue; - } else if (xp.parse_bool("non_cpu_intensive", non_cpu_intensive)) { - continue; } else if (xp.parse_bool("ended", ended)) { continue; } else if (xp.parse_bool("no_cpu_apps", btemp)) { diff --git a/lib/Makefile.linux b/lib/Makefile.linux index 6f65599813a..8d6881cade2 100644 --- a/lib/Makefile.linux +++ b/lib/Makefile.linux @@ -1,6 +1,7 @@ # make libraries for Linux client and boinccmd -CC = g++ -O4 -Wall -I ../ +//CC = g++ -O4 -Wall -I ../ +CC = g++ -g -Wall -I ../ all: boinc.a boinc_cmd.a diff --git a/samples/sporadic/sporadic.cpp b/samples/sporadic/sporadic.cpp index 6ccca82b223..9f2b952af21 100644 --- a/samples/sporadic/sporadic.cpp +++ b/samples/sporadic/sporadic.cpp @@ -11,14 +11,14 @@ // in a real app you'd want to use threads #define NWAIT 10 -#define NCOMP 30 +#define NCOMP 10 #include "boinc_api.h" #include "util.h" #include "common_defs.h" -void boinc_sporadic_set_ac_state(AC_STATE); -CA_STATE boinc_sporadic_get_ca_state(); +void boinc_sporadic_set_ac_state(SPORADIC_AC_STATE); +SPORADIC_CA_STATE boinc_sporadic_get_ca_state(); void print_state() { } @@ -27,7 +27,7 @@ void compute_one_sec() { double start = dtime(); while (1) { double x = 0; - for (int i=0; i<1e9; i++) { + for (int i=0; i<1e8; i++) { x += 1; } if (dtime() > start+1) break; @@ -36,20 +36,25 @@ void compute_one_sec() { int main(int, char**) { boinc_init(); - CA_STATE ca_state; - AC_STATE ac_state; + SPORADIC_CA_STATE ca_state; + SPORADIC_AC_STATE ac_state; + fprintf(stderr, "starting\n"); while (true) { // wait for a bit ac_state = AC_DONT_WANT_COMPUTE; boinc_sporadic_set_ac_state(ac_state); for (int i=0; i Date: Mon, 2 Oct 2023 12:51:19 -0700 Subject: [PATCH 03/14] Intermediate checkin. Sporadic app feature is complete (I think) but not tested. - Add code to SPORADIC_RESOURCES to check and reserve coprocs - Subtract sporadic resources before scheduling regular jobs - Move SPORADIC_RESOURCES to coproc_sched.h, making it visible to other code - Change 'have_sporadic' to 'have_sporadic_app'; we use the word 'sporadic' for network connections too --- client/app_test.cpp | 2 +- client/client_state.cpp | 4 +-- client/client_state.h | 2 +- client/client_types.cpp | 2 +- client/coproc_sched.cpp | 2 +- client/coproc_sched.h | 76 ++++++++++++++++++++++++++++++++++++++++- client/cpu_sched.cpp | 17 +++++++++ 7 files changed, 98 insertions(+), 7 deletions(-) diff --git a/client/app_test.cpp b/client/app_test.cpp index 229435981d5..9869956b407 100644 --- a/client/app_test.cpp +++ b/client/app_test.cpp @@ -40,7 +40,7 @@ void CLIENT_STATE::app_test_init() { app->project = proj; // can put other stuff here like app->sporadic = true; - have_sporadic = true; + have_sporadic_app = true; apps.push_back(app); FILE_INFO *fip = new FILE_INFO; diff --git a/client/client_state.cpp b/client/client_state.cpp index 92105270828..3b80bc1b0e8 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -186,7 +186,7 @@ CLIENT_STATE::CLIENT_STATE() #ifdef _WIN32 have_sysmon_msg = false; #endif - have_sporadic = false; + have_sporadic_app = false; } void CLIENT_STATE::show_host_info() { @@ -1166,7 +1166,7 @@ bool CLIENT_STATE::poll_slow_events() { if (!network_suspended) { POLL_ACTION(scheduler_rpc , scheduler_rpc_poll ); } - if (have_sporadic) { + if (have_sporadic_app) { sporadic_poll(); } retval = write_state_file_if_needed(); diff --git a/client/client_state.h b/client/client_state.h index 7b61a8b40ad..c1bbb2b9e91 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -461,7 +461,7 @@ struct CLIENT_STATE { bool scheduler_rpc_poll(); // --------------- cs_sporadic.cpp: - bool have_sporadic; + bool have_sporadic_app; void sporadic_poll(); void sporadic_init(); diff --git a/client/client_types.cpp b/client/client_types.cpp index ce21fab4dcf..2bac026ccf7 100644 --- a/client/client_types.cpp +++ b/client/client_types.cpp @@ -156,7 +156,7 @@ int APP::parse(XML_PARSER& xp) { if (xp.parse_bool("sporadic", sporadic)) continue; if (xp.parse_bool("fraction_done_exact", fraction_done_exact)) continue; if (xp.parse_bool("sporadic", sporadic)) { - if (sporadic) gstate.have_sporadic = true; + if (sporadic) gstate.have_sporadic_app = true; continue; } #ifdef SIM diff --git a/client/coproc_sched.cpp b/client/coproc_sched.cpp index ec33283c633..1f1c65356bf 100644 --- a/client/coproc_sched.cpp +++ b/client/coproc_sched.cpp @@ -45,7 +45,7 @@ using std::vector; // COPROC::pending_usage[]: for each instance, its usage by running jobs // Note: "running" includes jobs suspended due to CPU throttling. // That's the only kind of suspended GPU job. -// CORPOC::usage[]: for each instance, its usage +// COPROC::usage[]: for each instance, its usage // // enforce_run_list() calls assign_coprocs(), // which assigns coproc instances to scheduled jobs, diff --git a/client/coproc_sched.h b/client/coproc_sched.h index 4525558cb9b..6f3ae8852d0 100644 --- a/client/coproc_sched.h +++ b/client/coproc_sched.h @@ -1,6 +1,6 @@ // This file is part of BOINC. // http://boinc.berkeley.edu -// Copyright (C) 2014 University of California +// Copyright (C) 2023 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 @@ -15,8 +15,82 @@ // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . +// stuff related to scheduling coprocessors + #include struct RESULT; extern void assign_coprocs(std::vector& jobs); + +// The resources (proc and mem) used by running sporadic jobs. +// We recompute these on each poll, since e.g. WSS can change. +// +// Note: this is similar to (but simpler than) +// the PROC_RESOURCES struct in cpu_sched.cpp. +// Perhaps the two could be merged; for now, easier to keep them separate. +// +struct SPORADIC_RESOURCES { + double ncpus_used, ncpus_max; + double mem_used, mem_max; + COPROCS sp_coprocs; + + // clear reservations; called on each poll + void init_poll() { + ncpus_used= 0; + mem_used = 0; + sp_coprocs.clear_usage(); + } + // called once at start + void init() { + sp_coprocs.clone(coprocs, false); + init_poll(); + } + // are there enough free resources to run the task? + bool enough(ACTIVE_TASK *atp) { + if (mem_used + atp->procinfo.working_set_size_smoothed > mem_max) { + return false; + } + RESULT *rp = atp->result; + APP_VERSION *avp = rp->avp; + if (ncpus_used + avp->avg_ncpus > ncpus_max) { + return false; + } + int rt = avp->gpu_usage.rsc_type; + bool found = false; + if (rt) { + double u = avp->gpu_usage.usage; + COPROC& cp = sp_coprocs.coprocs[rt]; + for (int i=0; iapp, cp, i)) continue; + if (u + cp.usage[i] <= 1) { + found = true; + break; + } + } + if (!found) return false; + } + return true; + } + // reserve resources for the task + void reserve(ACTIVE_TASK *atp) { + RESULT *rp = atp->result; + APP_VERSION *avp = rp->avp; + mem_used += atp->procinfo.working_set_size_smoothed; + ncpus_used+= avp->avg_ncpus; + int rt = avp->gpu_usage.rsc_type; + if (rt) { + double u = avp->gpu_usage.usage; + COPROC& cp = sp_coprocs.coprocs[rt]; + for (int i=0; iapp, cp, i)) continue; + if (u + cp.usage[i] <= 1) { + cp.usage[i] += u; + break; + } + } + } + } +}; + +extern SPORADIC_RESOURCES sporadic_resources; diff --git a/client/cpu_sched.cpp b/client/cpu_sched.cpp index 390b5b6ad2e..880e4296c48 100644 --- a/client/cpu_sched.cpp +++ b/client/cpu_sched.cpp @@ -882,6 +882,20 @@ void CLIENT_STATE::make_run_list(vector& run_list) { proc_rsc.init(); + // if there are sporadic apps, + // subtract the resource usage of those that are computing + // + if (have_sporadic_app) { + proc_rsc.ncpus -= sporadic_resources.ncpus_used; + for (int i=1; i& run_list) { } double ram_left = available_ram(); + if (have_sporadic_app) { + ram_left -= sporadic_resources.mem_used; + } double swap_left = (global_prefs.vm_max_used_frac)*host_info.m_swap; if (log_flags.mem_usage_debug) { From 41e439acf604e194faacb3c5ca10c3bb6ecad5e6 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 2 Oct 2023 13:00:00 -0700 Subject: [PATCH 04/14] add file --- client/cs_sporadic.cpp | 225 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 client/cs_sporadic.cpp diff --git a/client/cs_sporadic.cpp b/client/cs_sporadic.cpp new file mode 100644 index 00000000000..c196a6a8677 --- /dev/null +++ b/client/cs_sporadic.cpp @@ -0,0 +1,225 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2023 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 . + +// logic for handling sporadic jobs +// +// Currently sporadic jobs have priority over others. +// In particular, they can preempt jobs that +// - are in danger of missing their deadline +// - have done a lot of computing and haven't checkpointed +// - are from projects with a resource share debt +// At some point we should fix this. + +// Apps can be +// regular: jobs compute when running +// sporadic: jobs run all the time but compute only part of the time +// non-CPU-intensive (NCI): jobs run all the time but don't compute +// +// Projects can have any or all of these, and this can change over time. +// A project is flagged as NCI if it has only NCI apps; +// in that case it's omitted from resource share calculations. + +// Note: the client and app communicate via 1-way streams +// that are polled once/sec. +// This introduces potential uncertainty: +// if we send the app a message, +// once second later we don't know if it received the message and responded. +// To avoid this problem, when we send a message to an app +// we ignore its messages for the next 2.5 seconds. +// Perhaps a better approach would be to use sequence numbers and acks. +// +// states and transitions: +// CA_DONT_COMPUTE +// computing is suspended, or insufficient resources +// transitions: +// to COULD_COMPUTE when these no longer hold +// CA_COULD_COMPUTE +// not computing, but could +// transitions: +// to CA_DONT_COMPUTE if computing suspended or insufficient resources +// to CA_COMPUTING if get AC_WANT_COMPUTE +// CA_COMPUTING +// job can compute (and is, as far as we know) +// transitions: +// to CA_DONT_COMPUTE if computing suspended or insufficient resources +// to CA_DONT_COMPUTE if get AC_DONT_WANT_COMPUTE or AC_NONE +// (after timeout - see above) +// +// Interaction with the batch scheduler: +// If we make a transition that changes resource usage, +// request a reschedule to start/stop batch jobs +// The batch scheduler subtracts resources used by sporadic jobs +// Coprocs: +// If batch jobs are using GPUs, it may take them a few seconds to exit. +// Sporadic jobs that use GPUs should delay for a few seconds at start, +// and retry failed VRAM allocations. +// + +#include "coproc.h" + +#include "client_state.h" +#include "client_msgs.h" +#include "coproc_sched.h" +#include "result.h" +#include "app.h" + +#define SPORADIC_MSG_DELAY 2.5 + +SPORADIC_RESOURCES sporadic_resources; + +// is computing suspended for this job? +// +static bool computing_suspended(ACTIVE_TASK *atp) { + if (gstate.suspend_reason) return true; + if (atp->result->uses_gpu() && gpu_suspend_reason) return true; + return false; +} + +// polling routine, called once/sec +void CLIENT_STATE::sporadic_poll() { + sporadic_resources.init_poll(); + sporadic_resources.mem_max = available_ram(); + sporadic_resources.ncpus_max = n_usable_cpus; + + bool changed_active = false; + // whether we need to reschedule regular jobs + + // find jobs that are active but shouldn't be + // (CA_COMPUTING -> CA_NONE transitions) + // + for (ACTIVE_TASK *atp: active_tasks.active_tasks) { + if (!atp->sporadic()) continue; + if (atp->sporadic_ca_state != CA_COMPUTING) continue; + + // the job is in state CA_COMPUTING + + // see if the job needs to stop computing + if (computing_suspended(atp)) { + atp->sporadic_ca_state = CA_NONE; + changed_active = true; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] preempting %s: computing suspended", + atp->result->name + ); + } + } else if (!sporadic_resources.enough(atp)) { + // this could happen if user prefs change + atp->sporadic_ca_state = CA_NONE; + changed_active = true; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] preempting %s: insufficient resources", + atp->result->name + ); + } + } else if (atp->sporadic_ac_state != AC_WANT_COMPUTE) { + if (now > atp->sporadic_ignore_until) { + atp->sporadic_ca_state = CA_NONE; + changed_active = true; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] %s: app is done computing", + atp->result->name + ); + } + } + } + // the job can keep computing - reserve its resources + if (atp->sporadic_ca_state == CA_COMPUTING) { + sporadic_resources.reserve(atp); + } + } + + // activate jobs as needed + // (CA_COULD_COMPUTE -> CA_COMPUTING transitions) + // + for (ACTIVE_TASK *atp: active_tasks.active_tasks) { + if (!atp->sporadic()) continue; + if (atp->sporadic_ca_state != CA_COULD_COMPUTE) continue; + if (computing_suspended(atp)) { + atp->sporadic_ca_state = CA_DONT_COMPUTE; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] %s can no longer compute: suspended", + atp->result->name + ); + } + } else if (!sporadic_resources.enough(atp)) { + atp->sporadic_ca_state = CA_DONT_COMPUTE; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] %s can no longer compute: insufficient resources", + atp->result->name + ); + } + } else if (atp->sporadic_ac_state == AC_WANT_COMPUTE) { + if (now > atp->sporadic_ignore_until) { + atp->sporadic_ca_state = CA_COMPUTING; + atp->sporadic_ignore_until = now + SPORADIC_MSG_DELAY; + sporadic_resources.reserve(atp); + changed_active = true; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] starting %s", + atp->result->name + ); + } + } + } + } + + // assign states to initial, preempted, and done jobs + // + for (ACTIVE_TASK *atp: active_tasks.active_tasks) { + if (!atp->sporadic()) continue; + if (atp->sporadic_ca_state != CA_NONE) continue; + if (computing_suspended(atp)) { + atp->sporadic_ca_state = CA_DONT_COMPUTE; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] %s can't compute: suspended", + atp->result->name + ); + } + } else if (!sporadic_resources.enough(atp)) { + atp->sporadic_ca_state = CA_DONT_COMPUTE; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] %s can't compute: insufficient resources", + atp->result->name + ); + } + } else { + atp->sporadic_ca_state = CA_COULD_COMPUTE; + if (log_flags.sporadic_debug) { + msg_printf(atp->result->project, MSG_INFO, + "[sporadic] %s can compute", + atp->result->name + ); + } + } + } + + if (changed_active) { + request_schedule_cpus("sporadic apps changed state"); + } +} + +void CLIENT_STATE::sporadic_init() { + sporadic_resources.init(); +} From 05367177e92b08434e816b495b24f976821012da Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 2 Oct 2023 13:04:40 -0700 Subject: [PATCH 05/14] fix compile warning --- client/cpu_sched.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cpu_sched.cpp b/client/cpu_sched.cpp index 880e4296c48..5a57a8cf291 100644 --- a/client/cpu_sched.cpp +++ b/client/cpu_sched.cpp @@ -887,9 +887,9 @@ void CLIENT_STATE::make_run_list(vector& run_list) { // if (have_sporadic_app) { proc_rsc.ncpus -= sporadic_resources.ncpus_used; - for (int i=1; i Date: Mon, 2 Oct 2023 13:05:51 -0700 Subject: [PATCH 06/14] update VS project file --- win_build/boinc_cli.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/win_build/boinc_cli.vcxproj b/win_build/boinc_cli.vcxproj index 4c22ebf11d5..1103526fd84 100644 --- a/win_build/boinc_cli.vcxproj +++ b/win_build/boinc_cli.vcxproj @@ -314,6 +314,7 @@ + From b7eee0c1908cef78216387fe4871bf0cc2ae3af3 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 2 Oct 2023 21:23:13 -0700 Subject: [PATCH 07/14] add debugging code --- client/coproc_sched.h | 15 ++++++++++----- client/cpu_sched.cpp | 2 +- client/cs_sporadic.cpp | 20 ++++++++++++++++++++ samples/sporadic/sporadic.cpp | 3 --- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/client/coproc_sched.h b/client/coproc_sched.h index 6f3ae8852d0..d15a7ca54a3 100644 --- a/client/coproc_sched.h +++ b/client/coproc_sched.h @@ -33,19 +33,21 @@ extern void assign_coprocs(std::vector& jobs); struct SPORADIC_RESOURCES { double ncpus_used, ncpus_max; double mem_used, mem_max; - COPROCS sp_coprocs; + COPROCS sr_coprocs; // clear reservations; called on each poll void init_poll() { ncpus_used= 0; mem_used = 0; - sp_coprocs.clear_usage(); + sr_coprocs.clear_usage(); } + // called once at start void init() { - sp_coprocs.clone(coprocs, false); + sr_coprocs.clone(coprocs, false); init_poll(); } + // are there enough free resources to run the task? bool enough(ACTIVE_TASK *atp) { if (mem_used + atp->procinfo.working_set_size_smoothed > mem_max) { @@ -60,7 +62,7 @@ struct SPORADIC_RESOURCES { bool found = false; if (rt) { double u = avp->gpu_usage.usage; - COPROC& cp = sp_coprocs.coprocs[rt]; + COPROC& cp = sr_coprocs.coprocs[rt]; for (int i=0; iapp, cp, i)) continue; if (u + cp.usage[i] <= 1) { @@ -72,6 +74,7 @@ struct SPORADIC_RESOURCES { } return true; } + // reserve resources for the task void reserve(ACTIVE_TASK *atp) { RESULT *rp = atp->result; @@ -81,7 +84,7 @@ struct SPORADIC_RESOURCES { int rt = avp->gpu_usage.rsc_type; if (rt) { double u = avp->gpu_usage.usage; - COPROC& cp = sp_coprocs.coprocs[rt]; + COPROC& cp = sr_coprocs.coprocs[rt]; for (int i=0; iapp, cp, i)) continue; if (u + cp.usage[i] <= 1) { @@ -91,6 +94,8 @@ struct SPORADIC_RESOURCES { } } } + + void print(); }; extern SPORADIC_RESOURCES sporadic_resources; diff --git a/client/cpu_sched.cpp b/client/cpu_sched.cpp index 5a57a8cf291..d844cda29ef 100644 --- a/client/cpu_sched.cpp +++ b/client/cpu_sched.cpp @@ -889,7 +889,7 @@ void CLIENT_STATE::make_run_list(vector& run_list) { proc_rsc.ncpus -= sporadic_resources.ncpus_used; for (int rt=1; rt 0) { + msg_printf(NULL, MSG_INFO, " GPU %s instance %d: %f\n", + cp.type, j, cp.usage[j] + ); + } + } + } +} + // is computing suspended for this job? // static bool computing_suspended(ACTIVE_TASK *atp) { @@ -218,6 +234,10 @@ void CLIENT_STATE::sporadic_poll() { if (changed_active) { request_schedule_cpus("sporadic apps changed state"); } + + if (log_flags.sporadic_debug) { + sporadic_resources.print(); + } } void CLIENT_STATE::sporadic_init() { diff --git a/samples/sporadic/sporadic.cpp b/samples/sporadic/sporadic.cpp index 9f2b952af21..294fc22a0e3 100644 --- a/samples/sporadic/sporadic.cpp +++ b/samples/sporadic/sporadic.cpp @@ -20,9 +20,6 @@ void boinc_sporadic_set_ac_state(SPORADIC_AC_STATE); SPORADIC_CA_STATE boinc_sporadic_get_ca_state(); -void print_state() { -} - void compute_one_sec() { double start = dtime(); while (1) { From 20fe4ab4d38761b0c41e01124e7bea04ef3fdda2 Mon Sep 17 00:00:00 2001 From: davidpanderson Date: Tue, 3 Oct 2023 13:37:12 -0700 Subject: [PATCH 08/14] debugging code --- client/app_test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/app_test.cpp b/client/app_test.cpp index 9869956b407..e63723730c9 100644 --- a/client/app_test.cpp +++ b/client/app_test.cpp @@ -62,6 +62,10 @@ void CLIENT_STATE::app_test_init() { av->app_files.push_back(*fref); // can put other stuff here like av->avg_ncpus = 1; + av->flops = 1e9; + av->gpu_ram = 1e7; + av->gpu_usage.rsc_type = PROC_TYPE_NVIDIA_GPU; + av->gpu_usage.usage = 1; app_versions.push_back(av); WORKUNIT *wu = new WORKUNIT; From ad0d4214d60d30240cf3d3271bc322ac0b1fd7b8 Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Wed, 4 Oct 2023 04:06:15 -0700 Subject: [PATCH 09/14] update Xcode project file --- mac_build/boinc.xcodeproj/project.pbxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mac_build/boinc.xcodeproj/project.pbxproj b/mac_build/boinc.xcodeproj/project.pbxproj index edaecae0614..c74569ec4c9 100644 --- a/mac_build/boinc.xcodeproj/project.pbxproj +++ b/mac_build/boinc.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ DD0052F910CA6F1D0067570C /* cs_proxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD0052F710CA6F1D0067570C /* cs_proxy.cpp */; }; DD00F554176C081500850424 /* MacInstaller.icns in Resources */ = {isa = PBXBuildFile; fileRef = DD531BC50C193D3800742E50 /* MacInstaller.icns */; }; DD01B6790C16723C0023A806 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; + DD0428462ACD7D3F00229B6D /* cs_sporadic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD0428452ACD7D3F00229B6D /* cs_sporadic.cpp */; }; DD08648D19E0BE6D00994039 /* ProjectWelcomePage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD08648B19E0BE6D00994039 /* ProjectWelcomePage.cpp */; }; DD0925B51FB05490000902DF /* project_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD0925B31FB05490000902DF /* project_list.cpp */; }; DD0A06F50869A2D2007CD86E /* prefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD344BE407C5B1670043025C /* prefs.cpp */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -899,6 +900,7 @@ DD000D7324D0244C0083DE77 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = ""; }; DD0052F710CA6F1D0067570C /* cs_proxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cs_proxy.cpp; path = ../client/cs_proxy.cpp; sourceTree = SOURCE_ROOT; }; DD0052F810CA6F1D0067570C /* cs_proxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cs_proxy.h; path = ../client/cs_proxy.h; sourceTree = SOURCE_ROOT; }; + DD0428452ACD7D3F00229B6D /* cs_sporadic.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = cs_sporadic.cpp; sourceTree = ""; }; DD04BE1A0EDD836A006D5603 /* TermsOfUsePage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TermsOfUsePage.h; path = ../clientgui/TermsOfUsePage.h; sourceTree = SOURCE_ROOT; }; DD08648B19E0BE6D00994039 /* ProjectWelcomePage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectWelcomePage.cpp; sourceTree = ""; }; DD08648C19E0BE6D00994039 /* ProjectWelcomePage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectWelcomePage.h; sourceTree = ""; }; @@ -2119,6 +2121,7 @@ DD0052F710CA6F1D0067570C /* cs_proxy.cpp */, DD0052F810CA6F1D0067570C /* cs_proxy.h */, F54B8FC902AC0A0C01FB7237 /* cs_scheduler.cpp */, + DD0428452ACD7D3F00229B6D /* cs_sporadic.cpp */, DD344B9307C5AE2E0043025C /* cs_statefile.cpp */, DD344B9407C5AE2E0043025C /* cs_trickle.cpp */, B13E2D162655655000D5C977 /* detect_rosetta_cpu.cpp */, @@ -4002,6 +4005,7 @@ DDD74D9707CF48F30065AC9D /* cs_files.cpp in Sources */, DDD74D9807CF48F40065AC9D /* cs_prefs.cpp in Sources */, DDD74D9907CF48F50065AC9D /* cs_scheduler.cpp in Sources */, + DD0428462ACD7D3F00229B6D /* cs_sporadic.cpp in Sources */, DD0925B51FB05490000902DF /* project_list.cpp in Sources */, DDD74D9A07CF48F60065AC9D /* cs_statefile.cpp in Sources */, DDD74D9B07CF48F90065AC9D /* cs_trickle.cpp in Sources */, From 227d0cb780efadd27be669b9285c7b7534831f27 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 4 Oct 2023 17:04:13 -0700 Subject: [PATCH 10/14] remove space --- client/cs_sporadic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cs_sporadic.cpp b/client/cs_sporadic.cpp index c88ecfcc3ee..939b9a8916e 100644 --- a/client/cs_sporadic.cpp +++ b/client/cs_sporadic.cpp @@ -67,7 +67,7 @@ // If batch jobs are using GPUs, it may take them a few seconds to exit. // Sporadic jobs that use GPUs should delay for a few seconds at start, // and retry failed VRAM allocations. -// +// #include "coproc.h" From 97addef5ac1baf9268bf5ed6b86b7359a80e29fd Mon Sep 17 00:00:00 2001 From: davidpanderson Date: Wed, 4 Oct 2023 17:24:42 -0700 Subject: [PATCH 11/14] Win: fix simulator build --- win_build/sim.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/win_build/sim.vcxproj b/win_build/sim.vcxproj index 3932994a842..79b686746d8 100644 --- a/win_build/sim.vcxproj +++ b/win_build/sim.vcxproj @@ -306,6 +306,7 @@ + From f68798b39fd42eaaf872428330fae0e71ef1f278 Mon Sep 17 00:00:00 2001 From: Vitalii Koshura Date: Thu, 5 Oct 2023 17:57:26 +0200 Subject: [PATCH 12/14] Add sporadic sample application to the MSVC solution Signed-off-by: Vitalii Koshura --- win_build/boinc.sln | 10 ++ win_build/sporadic.vcxproj | 278 +++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 win_build/sporadic.vcxproj diff --git a/win_build/boinc.sln b/win_build/boinc.sln index 2b17cbfb12b..d613d033c04 100644 --- a/win_build/boinc.sln +++ b/win_build/boinc.sln @@ -128,6 +128,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crypt_prog", "crypt_prog.vc {D3E5B5B5-4FB1-4877-9B2C-6708B3D568F7} = {D3E5B5B5-4FB1-4877-9B2C-6708B3D568F7} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_app_sporadic", "sporadic.vcxproj", "{0740E6DC-ADE7-4272-BAB0-52DE62325D3E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -422,6 +424,14 @@ Global {C04F0F2C-B75D-4628-8656-6163B28BD69E}.Release|ARM64.Build.0 = Release|ARM64 {C04F0F2C-B75D-4628-8656-6163B28BD69E}.Release|x64.ActiveCfg = Release|x64 {C04F0F2C-B75D-4628-8656-6163B28BD69E}.Release|x64.Build.0 = Release|x64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Debug|ARM64.Build.0 = Debug|ARM64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Debug|x64.ActiveCfg = Debug|x64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Debug|x64.Build.0 = Debug|x64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Release|ARM64.ActiveCfg = Release|ARM64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Release|ARM64.Build.0 = Release|ARM64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Release|x64.ActiveCfg = Release|x64 + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/win_build/sporadic.vcxproj b/win_build/sporadic.vcxproj new file mode 100644 index 00000000000..be517991772 --- /dev/null +++ b/win_build/sporadic.vcxproj @@ -0,0 +1,278 @@ + + + + + + Debug + ARM64 + + + Debug + x64 + + + Release + ARM64 + + + Release + x64 + + + + example_app_sporadic + {0740E6DC-ADE7-4272-BAB0-52DE62325D3E} + + + + Application + MultiByte + v143 + + + Application + MultiByte + v143 + + + Application + MultiByte + v143 + + + Application + MultiByte + v143 + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)Build\$(Platform)\$(Configuration)\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\$(ProjectName)\obj\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\$(ProjectName)\obj\ + + + $(SolutionDir)Build\$(Platform)\$(Configuration)\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\$(ProjectName)\obj\ + $(SolutionDir)Build\$(Platform)\$(Configuration)\$(ProjectName)\obj\ + + + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + + + + + + + MaxSpeed + OnlyExplicitInline + Speed + .;..;../api;../lib;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + Sync + MultiThreaded + true + + + boinc_win.h + $(IntDir)boinc_win.pch + + + CompileAsCpp + boinc_win.h;%(ForcedIncludeFiles) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + libcmt.lib;libcpmt.lib;%(AdditionalDependencies) + true + false + %(DelayLoadDLLs) + .\Build\$(Platform)\$(Configuration)\$(ProjectName).pdb + Console + MachineX64 + $(OutDir) + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + + + + + + + MaxSpeed + OnlyExplicitInline + Speed + .;..;../api;../lib;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + Sync + MultiThreaded + true + + + boinc_win.h + $(IntDir)boinc_win.pch + + + CompileAsCpp + boinc_win.h;%(ForcedIncludeFiles) + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + libcmt.lib;libcpmt.lib;%(AdditionalDependencies) + true + false + %(DelayLoadDLLs) + .\Build\$(Platform)\$(Configuration)\$(ProjectName).pdb + Console + $(OutDir) + + + + + %(PreprocessorDefinitions) + true + true + X64 + + + + + + + Disabled + .;..;../api;../lib;%(AdditionalIncludeDirectories) + WIN32;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + boinc_win.h + $(IntDir)boinc_win.pch + + + CompileAsCpp + %(ForcedIncludeFiles) + + + %(PreprocessorDefinitions) + 0x0409 + + + libcmtd.lib;libcpmtd.lib;kernel32.lib;user32.lib;delayimp.lib;%(AdditionalDependencies) + true + false + %(DelayLoadDLLs) + .\Build\$(Platform)\$(Configuration)\$(ProjectName).pdb + Console + MachineX64 + $(OutDir) + + + + + %(PreprocessorDefinitions) + true + true + + + + + + + Disabled + .;..;../api;../lib;%(AdditionalIncludeDirectories) + WIN32;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + boinc_win.h + $(IntDir)boinc_win.pch + + + CompileAsCpp + %(ForcedIncludeFiles) + + + %(PreprocessorDefinitions) + 0x0409 + + + libcmtd.lib;libcpmtd.lib;kernel32.lib;user32.lib;delayimp.lib;%(AdditionalDependencies) + true + false + %(DelayLoadDLLs) + .\Build\$(Platform)\$(Configuration)\$(ProjectName).pdb + Console + $(OutDir) + + + + + + + + {07bda8f7-4aaf-4a3b-b96e-ea72a143c5ae} + false + + + {e8f6bd7e-461a-4733-b7d8-37b09a099ed8} + + + + + + + \ No newline at end of file From 9f80b5ca136fb3865e9852fbbd68c13541fd7b1b Mon Sep 17 00:00:00 2001 From: Vitalii Koshura Date: Fri, 6 Oct 2023 02:08:50 +0200 Subject: [PATCH 13/14] Add sporadic sample app to the linux and android CI pipelines Signed-off-by: Vitalii Koshura --- deploy/prepare_deployment.py | 14 +++++++-- samples/Makefile.am | 2 +- samples/sporadic/Makefile | 59 +++++++++++++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/deploy/prepare_deployment.py b/deploy/prepare_deployment.py index 9d9a8a147b7..a8d0a12d5aa 100644 --- a/deploy/prepare_deployment.py +++ b/deploy/prepare_deployment.py @@ -42,7 +42,8 @@ './samples/wrapper/wrapper', './samples/openclapp/openclapp', './samples/wrappture/wrappture_example', - './samples/wrappture/fermi' + './samples/wrappture/fermi', + './samples/sporadic/sporadic' ] linux_manager_list = [ @@ -67,7 +68,8 @@ './samples/worker/worker.exe', './samples/wrapper/wrapper.exe', './samples/wrappture/wrappture_example.exe', - './samples/wrappture/fermi.exe' + './samples/wrappture/fermi.exe', + './samples/sporadic/sporadic.exe' ] android_manager_generic_list = [ @@ -139,7 +141,13 @@ './samples/wrappture/android_arm_fermi', './samples/wrappture/android_arm64_fermi', './samples/wrappture/android_x86_fermi', - './samples/wrappture/android_x86_64_fermi' + './samples/wrappture/android_x86_64_fermi', + # sporadic + './samples/sporadic/android_armv6_sporadic', + './samples/sporadic/android_arm_sporadic', + './samples/sporadic/android_arm64_sporadic', + './samples/sporadic/android_x86_sporadic', + './samples/sporadic/android_x86_64_sporadic' ] windows_apps_list = [ diff --git a/samples/Makefile.am b/samples/Makefile.am index e2cd86a4521..ca89532b4f8 100644 --- a/samples/Makefile.am +++ b/samples/Makefile.am @@ -16,7 +16,7 @@ endif ## list the apps that should be build ## NOTE: nvcuda and wrappture need external libraries -SUBDIRS = condor example_app multi_thread sleeper worker wrapper +SUBDIRS = condor example_app multi_thread sleeper sporadic worker wrapper if BUILD_WITH_VBOX SUBDIRS += vboxmonitor vboxwrapper diff --git a/samples/sporadic/Makefile b/samples/sporadic/Makefile index 4d6eff1ec12..7a9be28f283 100644 --- a/samples/sporadic/Makefile +++ b/samples/sporadic/Makefile @@ -1,8 +1,57 @@ + +BOINC_DIR = ../.. +BOINC_SOURCE_API_DIR = $(BOINC_DIR)/api +BOINC_SOURCE_LIB_DIR = $(BOINC_DIR)/lib +BOINC_SOURCE_ZIP_DIR = $(BOINC_DIR)/zip + +ifdef ANDROID + BOINC_API_DIR = $(TCINCLUDES)/lib + BOINC_LIB_DIR = $(TCINCLUDES)/lib + BOINC_ZIP_DIR = $(TCINCLUDES)/lib + + MAKEFILE_LDFLAGS = + MAKEFILE_STDLIB = +else + BOINC_API_DIR = $(BOINC_SOURCE_API_DIR) + BOINC_LIB_DIR = $(BOINC_SOURCE_LIB_DIR) + BOINC_ZIP_DIR = $(BOINC_SOURCE_ZIP_DIR) + + MAKEFILE_LDFLAGS = -lpthread libstdc++.a + MAKEFILE_STDLIB = libstdc++.a +endif + +CXXFLAGS += -g \ + -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common \ + -I$(BOINC_DIR) \ + -I$(BOINC_SOURCE_API_DIR) \ + -I$(BOINC_SOURCE_LIB_DIR) \ + -I$(BOINC_SOURCE_ZIP_DIR) \ + -L$(BOINC_API_DIR) \ + -L$(BOINC_LIB_DIR) \ + -L. + +ifdef BUILD_WITH_VCPKG + BUILD_DIR = $(BOINC_DIR)/3rdParty/linux + VCPKG_DIR ?= $(BUILD_DIR)/vcpkg/installed/x64-linux + + CXXFLAGS += \ + -I$(VCPKG_DIR)/include \ + -L$(VCPKG_DIR)/lib +endif + all: sporadic -INC_DIRS = -I ../../api -I ../../lib -LIB_DIRS = -L ../../api -L ../../lib -CXX = g++ $(INC_DIRS) +libstdc++.a: + ln -s `$(CXX) -print-file-name=libstdc++.a` + +clean: distclean + +distclean: + /bin/rm -f sporadic $(addsuffix .exe, sporadic) *.o libstdc++.a + +install: sporadic -sporadic: sporadic.cpp - $(CXX) $(LIB_DIRS) sporadic.cpp -lboinc_api -lboinc -lpthread -o sporadic +sporadic: sporadic.o $(MAKEFILE_STDLIB) $(BOINC_API_DIR)/libboinc_api.a $(BOINC_LIB_DIR)/libboinc.a + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o sporadic sporadic.o \ + -lboinc_api -lboinc $(MAKEFILE_LDFLAGS) \ + $(STDCPPTC) From 52daa40b71292ea6e8d91d5184cf9df239659c2f Mon Sep 17 00:00:00 2001 From: Vitalii Koshura Date: Fri, 6 Oct 2023 02:28:05 +0200 Subject: [PATCH 14/14] Fix build with Android Signed-off-by: Vitalii Koshura --- android/buildAndroidBOINC-CI.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/buildAndroidBOINC-CI.sh b/android/buildAndroidBOINC-CI.sh index 1b87458b836..ad924d33742 100755 --- a/android/buildAndroidBOINC-CI.sh +++ b/android/buildAndroidBOINC-CI.sh @@ -260,7 +260,7 @@ vcpkgDir() echo $vcpkg_dir } -list_apps_name="boinc_gahp uc2 ucn multi_thread sleeper worker wrapper wrappture_example fermi" +list_apps_name="boinc_gahp uc2 ucn multi_thread sleeper sporadic worker wrapper wrappture_example fermi" NeonTest() { @@ -327,6 +327,7 @@ RenameAllApps() ../samples/example_app/ ucn ../samples/multi_thread/ multi_thread ../samples/sleeper/ sleeper + ../samples/sporadic/ sporadic ../samples/worker/ worker ../samples/wrapper/ wrapper ../samples/wrappture/ wrappture_example