Skip to content

Commit

Permalink
Merge pull request #5385 from BOINC/dpa_sporadic
Browse files Browse the repository at this point in the history
Client: add sporadic app feature
  • Loading branch information
AenBleidd committed Oct 6, 2023
2 parents 44295c1 + 52daa40 commit 71e5fd0
Show file tree
Hide file tree
Showing 40 changed files with 950 additions and 60 deletions.
3 changes: 2 additions & 1 deletion android/buildAndroidBOINC-CI.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions api/boinc_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -434,6 +435,10 @@ static bool update_app_progress(double cpu_t, double cp_cpu_t) {
snprintf(buf, sizeof(buf), "<bytes_received>%f</bytes_received>\n", bytes_received);
strlcat(msg_buf, buf, sizeof(msg_buf));
}
if (ac_state) {
sprintf(buf, "<sporadic_ac>%d</sporadic_ac>\n", ac_state);
strlcat(msg_buf, buf, sizeof(msg_buf));
}
#ifdef MSGS_FROM_FILE
if (fout) {
fputs(msg_buf, fout);
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

5 changes: 5 additions & 0 deletions api/boinc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions client/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 2 additions & 0 deletions client/Makefile.linux
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
3 changes: 3 additions & 0 deletions client/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ 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;
sporadic_ignore_until = 0;
}

bool ACTIVE_TASK::process_exists() {
Expand Down
16 changes: 16 additions & 0 deletions client/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "procinfo.h"

#include "client_types.h"
#include "result.h"

// values for preempt_type (see ACTIVE_TASK::preempt())
//
Expand Down Expand Up @@ -184,11 +185,26 @@ 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;
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();
Expand Down
22 changes: 16 additions & 6 deletions client/app_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,13 @@ void ACTIVE_TASK_SET::send_heartbeats() {
if (gstate.network_suspended) {
safe_strcat(buf, "<network_suspended/>");
}
if (atp->sporadic_ca_state != CA_NONE) {
char buf2[256];
sprintf(buf2, "<sporadic_ca>%d</sporadic_ca>",
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) {
Expand Down Expand Up @@ -889,7 +896,7 @@ bool ACTIVE_TASK_SET::check_rsc_limits_exceeded() {
for (i=0; i<active_tasks.size(); i++) {
atp = active_tasks[i];
if (atp->task_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,
Expand Down Expand Up @@ -943,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;
}
}
Expand Down Expand Up @@ -1206,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;
}
Expand All @@ -1218,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;
}
Expand Down Expand Up @@ -1246,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:
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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, "<sporadic_ac>", i)) {
sporadic_ac_state = (SPORADIC_AC_STATE)i;
}
if (current_cpu_time < 0) {
msg_printf(result->project, MSG_INFO,
"app reporting negative CPU: %f", current_cpu_time
Expand Down
10 changes: 7 additions & 3 deletions client/app_start.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions client/app_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ 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;
strcpy(app->name, "test app");
strcpy(app->user_friendly_name, "test app");
app->project = proj;
// can put other stuff here like
app->sporadic = true;
have_sporadic_app = true;
apps.push_back(app);

FILE_INFO *fip = new FILE_INFO;
Expand All @@ -56,6 +60,12 @@ 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;
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;
Expand Down
10 changes: 10 additions & 0 deletions client/client_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ CLIENT_STATE::CLIENT_STATE()
#ifdef _WIN32
have_sysmon_msg = false;
#endif
have_sporadic_app = false;
}

void CLIENT_STATE::show_host_info() {
Expand Down Expand Up @@ -858,6 +859,8 @@ int CLIENT_STATE::init() {
client_thread_mutex.lock();
throttle_thread.run(throttler, NULL);

sporadic_init();

initialized = true;
return 0;
}
Expand Down Expand Up @@ -949,6 +952,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;
Expand Down Expand Up @@ -1162,6 +1166,9 @@ bool CLIENT_STATE::poll_slow_events() {
if (!network_suspended) {
POLL_ACTION(scheduler_rpc , scheduler_rpc_poll );
}
if (have_sporadic_app) {
sporadic_poll();
}
retval = write_state_file_if_needed();
if (retval) {
msg_printf(NULL, MSG_INTERNAL_ERROR,
Expand Down Expand Up @@ -1269,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;
}

Expand Down
5 changes: 5 additions & 0 deletions client/client_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,11 @@ struct CLIENT_STATE {
bool had_or_requested_work;
bool scheduler_rpc_poll();

// --------------- cs_sporadic.cpp:
bool have_sporadic_app;
void sporadic_poll();
void sporadic_init();

// --------------- cs_statefile.cpp:
void set_client_state_dirty(const char*);
int parse_state_file();
Expand Down
6 changes: 6 additions & 0 deletions client/client_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -152,7 +153,12 @@ 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;
if (xp.parse_bool("sporadic", sporadic)) {
if (sporadic) gstate.have_sporadic_app = true;
continue;
}
#ifdef SIM
if (xp.parse_double("latency_bound", latency_bound)) continue;
if (xp.parse_double("fpops_est", fpops_est)) continue;
Expand Down

0 comments on commit 71e5fd0

Please sign in to comment.