project != p) continue;
if (rp->resource_type() != rsc_type) continue;
if (rp->state() < RESULT_FILES_UPLOADED) {
in_progress++;
} else {
done++;
}
}
}
void show_resource(int rsc_type) {
unsigned int i;
char buf[256];
fprintf(html_out, "", WIDTH2);
bool found = false;
for (i=0; iresult;
if (atp->task_state() != PROCESS_EXECUTING) continue;
double ninst=0;
if (rsc_type) {
if (rp->avp->gpu_usage.rsc_type != rsc_type) continue;
ninst = rp->avp->gpu_usage.usage;
} else {
ninst = rp->avp->avg_ncpus;
}
PROJECT* p = rp->project;
if (!found) {
found = true;
fprintf(html_out,
"\n"
"#devs | Job name (* = high priority) | GFLOPs left | %s \n",
rsc_type?"GPU | ":""
);
}
if (rsc_type) {
sprintf(buf, "%d | ", rp->coproc_indices[0]);
} else {
safe_strcpy(buf, "");
}
fprintf(html_out, "%.2f | %s%s | %.0f | %s \n",
ninst,
colors[p->index%NCOLORS],
rp->edf_scheduled?"*":"",
rp->name,
rp->sim_flops_left/1e9,
buf
);
}
if (found) {
fprintf(html_out, " \n");
} else {
fprintf(html_out, "IDLE\n");
}
fprintf(html_out,
"Project | In progress | done | REC | \n"
);
found = false;
for (i=0; i%s%d | %d | %.3f | \n",
colors[p->index%NCOLORS], p->project_name, in_progress, done,
p->pwf.rec
);
found = true;
}
}
//if (!found) fprintf(html_out, " ---\n");
fprintf(html_out, "
| ");
}
void html_start() {
char buf[256];
sprintf(buf, "%s%s", outfile_prefix, TIMELINE_FNAME);
html_out = fopen(buf, "w");
if (!html_out) {
fprintf(stderr, "can't open %s for writing\n", buf);
exit(1);
}
setbuf(html_out, 0);
fprintf(index_file, "
Timeline\n", TIMELINE_FNAME);
fprintf(html_out,
"\n"
"BOINC client emulator results
\n"
);
show_project_colors();
fprintf(html_out, "\n");
fprintf(html_out,
"\n"
);
}
void html_device_header() {
fprintf(html_out,
""
" %s | "
" CPU | ",
sim_time_string(gstate.now)
);
for (int i=1; i%s\n", name);
}
fprintf(html_out,
"
\n"
);
}
void html_write_message() {
fprintf(html_out,
""
" %s | "
" %s | "
"
\n",
sim_time_string(gstate.now),
html_msg.c_str()
);
}
// write the timeline row(s) for this time
//
void html_rec() {
if (html_msg.size()) {
html_write_message();
html_msg = "";
}
if (!active) {
fprintf(html_out,
""
" %s | "
" BOINC not running | "
"
",
sim_time_string(gstate.now)
);
} else {
html_device_header();
fprintf(html_out,
" | \n"
);
show_resource(0);
if (gpu_active) {
for (int i=1; iGPUs disabled");
}
}
fprintf(html_out,
"
\n"
);
}
}
void html_end() {
fprintf(html_out, "
\n");
fprintf(html_out, "\n");
sim_results.compute_figures_of_merit();
sim_results.print(html_out);
print_project_results(html_out);
fprintf(html_out, "
\n");
fclose(html_out);
}
void set_initial_rec() {
unsigned int i;
double sum=0;
double x = cpu_peak_flops() + gpu_peak_flops();
for (i=0; iresource_share;
}
for (i=0; ipwf.rec = 86400*x*(p->resource_share/sum)/1e9;
}
}
static bool compare_names(PROJECT* p1, PROJECT* p2) {
return (strcmp(p1->project_name, p2->project_name) < 0);
}
void write_recs() {
fprintf(rec_file, "%f ", gstate.now);
std::sort(
gstate.projects.begin(),
gstate.projects.end(),
compare_names
);
for (unsigned int i=0; ipwf.rec);
}
fprintf(rec_file, "\n");
}
void make_graph(const char* title, const char* fname, int field) {
char gp_fname[256], cmd[256], png_fname[256];
sprintf(gp_fname, "%s%s.gp", outfile_prefix, fname);
FILE* f = fopen(gp_fname, "w");
fprintf(f,
"set terminal png small size 1024, 768\n"
"set title \"%s\"\n"
"set yrange[0:]\n"
"plot ",
title
);
for (unsigned int i=0; iproject_name,
(i==gstate.projects.size()-1)?"\n":", \\\n"
);
}
fclose(f);
sprintf(png_fname, "%s%s.png", outfile_prefix, fname);
sprintf(cmd, "gnuplot < %s > %s", gp_fname, png_fname);
fprintf(index_file, "
Graph of %s\n", fname, title);
system(cmd);
}
static void write_inputs() {
char buf[256];
sprintf(buf, "%s/%s", outfile_prefix, INPUTS_FNAME);
FILE* f = fopen(buf, "w");
fprintf(f,
"Existing jobs only: %s\n"
"Round-robin only: %s\n"
"scheduler EDF sim: %s\n"
"Include empty projects: %s\n",
existing_jobs_only?"yes":"no",
cpu_sched_rr_only?"yes":"no",
server_uses_workload?"yes":"no",
include_empty_projects?"yes":"no"
);
fprintf(f,
"REC half-life: %f\n", cc_config.rec_half_life
);
fprintf(f,
"Simulation duration: %f\nTime step: %f\n",
duration, delta
);
fclose(f);
}
void simulate() {
bool action;
double start = START_TIME;
gstate.now = start;
html_start();
fprintf(summary_file,
"Hardware summary\n %d CPUs, %.1f GFLOPS\n",
gstate.host_info.p_ncpus, gstate.host_info.p_fpops/1e9
);
for (int i=1; iproject->project_name,
rp->name,
rsc_name_long(rp->avp->gpu_usage.rsc_type),
timediff_format(rp->sim_flops_left/rp->avp->flops).c_str(),
timediff_format(rp->report_deadline - START_TIME).c_str()
);
}
fprintf(summary_file,
"Simulation parameters\n"
" time step %f, duration %f\n"
"-------------------\n",
delta, duration
);
write_inputs();
while (1) {
on = on_proc.sample(delta);
if (on) {
active = active_proc.sample(delta);
if (active) {
gpu_active = gpu_active_proc.sample(delta);
} else {
gpu_active = false;
}
connected = connected_proc.sample(delta);
} else {
active = gpu_active = connected = false;
}
// do accounting for the period that just ended,
// even if we're now in an "off" state.
//
// need both of the following, else crash
//
action |= gstate.active_tasks.poll();
action |= gstate.handle_finished_apps();
if (on) {
while (1) {
action = false;
action |= gstate.schedule_cpus();
if (connected) {
action |= gstate.scheduler_rpc_poll();
// this deletes completed results
}
action |= gstate.active_tasks.poll();
action |= gstate.handle_finished_apps();
gpu_suspend_reason = gpu_active?0:1;
//msg_printf(0, MSG_INFO, action?"did action":"did no action");
if (!action) break;
}
}
//msg_printf(0, MSG_INFO, "took time step");
for (unsigned int i=0; itask_state() == PROCESS_EXECUTING) {
atp->elapsed_time += delta;
}
}
html_rec();
write_recs();
gstate.now += delta;
if (gstate.now > start + duration) break;
}
html_end();
}
void show_app(APP* app) {
fprintf(summary_file,
" app %s\n"
" job params: fpops_est %.0fG fpops mean %.0fG std_dev %.0fG\n"
" latency %.2f weight %.2f",
app->name, app->fpops_est/1e9,
app->fpops.mean/1e9, app->fpops.std_dev/1e9,
app->latency_bound,
app->weight
);
if (app->max_concurrent) {
fprintf(summary_file, " max_concurrent %d\n", app->max_concurrent);
} else {
fprintf(summary_file, "\n");
}
for (unsigned int i=0; iapp != app) continue;
if (avp->gpu_usage.rsc_type) {
fprintf(summary_file,
" app version %d (%s)\n"
" %.2f CPUs, %.2f %s GPUs, %.0f GFLOPS\n",
avp->version_num, avp->plan_class,
avp->avg_ncpus,
avp->gpu_usage.usage,
rsc_name(avp->gpu_usage.rsc_type),
avp->flops/1e9
);
} else {
fprintf(summary_file,
" app version %d (%s)\n"
" %.2f CPUs, %.0f GFLOPS\n",
avp->version_num, avp->plan_class,
avp->avg_ncpus,
avp->flops/1e9
);
}
}
}
// get application params,
// and set "ignore" for apps that have no versions or no params.
//
// App params can be specified in 2 ways:
// - the presence of a WU and result for that app
// - app.latency_bound and app.fpops_est are populated
//
void get_app_params() {
APP* app;
unsigned int i, j;
for (i=0; iapp;
double latency_bound = rp->report_deadline - rp->received_time;
if (!app->latency_bound) {
app->latency_bound = latency_bound;
}
rp->received_time = START_TIME;
rp->report_deadline = START_TIME + latency_bound;
rp->sim_flops_left = rp->wup->rsc_fpops_est;
}
for (i=0; iapp;
if (!app->fpops_est) {
app->fpops_est = wup->rsc_fpops_est;
}
}
for (i=0; iignore = true;
}
for (i=0; imissing_coproc) continue;
avp->app->ignore = false;
}
fprintf(summary_file, "Applications and version\n");
for (j=0; jproject_name);
for (i=0; iproject != p) continue;
if (app->ignore) {
fprintf(summary_file,
" app %s: ignoring - no usable app versions\n",
app->name
);
continue;
}
if (app->non_cpu_intensive) {
fprintf(summary_file,
" app %s: ignoring - non CPU intensive\n",
app->name
);
app->ignore = true;
continue;
}
// if missing app params, fill in defaults
//
if (!app->fpops_est) {
app->fpops_est = 3600e11;
}
if (!app->latency_bound) {
app->latency_bound = 864000;
}
if (!app->fpops_est || !app->latency_bound) {
app->ignore = true;
fprintf(summary_file,
" app %s: ignoring - no job parameters (see below)\n",
app->name
);
} else if (app->ignore) {
fprintf(summary_file,
" app %s: ignoring - no app versions\n",
app->name
);
} else {
if (!app->fpops.mean) {
app->fpops.mean = app->fpops_est;
}
if (!app->weight) {
app->weight = 1;
}
show_app(app);
}
}
}
fprintf(summary_file,
"\n"
"Note: an app's job parameters are taken from a job for that app.\n"
" They can also be specified by adding tags to client_state.xml.\n"
" See http://boinc.berkeley.edu/trac/wiki/ClientSim.\n"
"\n"
);
}
// zero backoffs and REC
//
void clear_backoff() {
unsigned int i;
for (i=0; irsc_pwf[j].reset();
}
p->min_rpc_time = 0;
}
}
// remove apps with no app versions,
// then projects with no apps
//
void cull_projects() {
unsigned int i;
PROJECT* p;
for (i=0; ino_apps = true;
}
for (i=0; iapp->ignore) continue;
}
for (i=0; iignore) {
app->project->no_apps = false;
}
}
for (i=0; ino_apps) {
fprintf(summary_file,
"%s: Removing from simulation - no apps\n",
p->project_name
);
p->ignore = true;
} else if (p->non_cpu_intensive) {
fprintf(summary_file,
"%s: Removing from simulation - non CPU intensive\n",
p->project_name
);
p->ignore = true;
}
}
// remove results and active tasks of projects we're culling
//
vector::iterator ati = gstate.active_tasks.active_tasks.begin();
while (ati != gstate.active_tasks.active_tasks.end()) {
ACTIVE_TASK* atp = *ati;
if (atp->wup->project->ignore) {
ati = gstate.active_tasks.active_tasks.erase(ati);
} else {
++ati;
}
}
vector::iterator ri = gstate.results.begin();
while (ri != gstate.results.end()) {
RESULT* rp = *ri;
if (rp->project->ignore) {
ri = gstate.results.erase(ri);
} else {
++ri;
}
}
vector::iterator iter = gstate.projects.begin();
while (iter != gstate.projects.end()) {
p = *iter;
if (p->ignore) {
iter = gstate.projects.erase(iter);
} else {
++iter;
}
}
}
void do_client_simulation() {
char buf[256], buf2[256];
int retval;
FILE* f;
sprintf(buf, "%s%s", infile_prefix, CONFIG_FILE);
cc_config.defaults();
read_config_file(true, buf);
log_flags.init();
sprintf(buf, "%s%s", outfile_prefix, "log_flags.xml");
f = fopen(buf, "r");
if (f) {
MIOFILE mf;
mf.init_file(f);
XML_PARSER xp(&mf);
xp.get_tag(); // skip open tag
log_flags.parse(xp);
fclose(f);
}
gstate.add_platform("client simulator");
sprintf(buf, "%s%s", infile_prefix, STATE_FILE_NAME);
if (!boinc_file_exists(buf)) {
fprintf(stderr, "No client state file\n");
exit(1);
}
retval = gstate.parse_state_file_aux(buf);
if (retval) {
fprintf(stderr, "state file parse error %d\n", retval);
exit(1);
}
// if tasks have pending transfers, mark as completed
//
for (unsigned int i=0; istate() < RESULT_FILES_DOWNLOADED) {
rp->set_state(RESULT_FILES_DOWNLOADED, "init");
} else if (rp->state() == RESULT_FILES_UPLOADING) {
rp->set_state(RESULT_FILES_UPLOADED, "init");
}
}
check_app_config(infile_prefix);
show_app_config();
cc_config.show();
log_flags.show();
sprintf(buf, "%s%s", infile_prefix, GLOBAL_PREFS_FILE_NAME);
sprintf(buf2, "%s%s", infile_prefix, GLOBAL_PREFS_OVERRIDE_FILE);
gstate.read_global_prefs(buf, buf2);
fprintf(index_file,
"Output files
\n"
"Summary\n"
"
Log file\n",
SUMMARY_FNAME, LOG_FNAME
);
// fill in GPU device nums and OpenCL flags
//
for (int i=0; iindex = j++;
}
clear_backoff();
gstate.log_show_projects();
gstate.set_ncpus();
work_fetch.init();
//set_initial_rec();
rec_adjust_period = delta;
gstate.request_work_fetch("init");
simulate();
sim_results.compute_figures_of_merit();
sprintf(buf, "%s%s", outfile_prefix, RESULTS_DAT_FNAME);
f = fopen(buf, "w");
sim_results.print(f);
fclose(f);
sprintf(buf, "%s%s", outfile_prefix, RESULTS_TXT_FNAME);
f = fopen(buf, "w");
sim_results.print(f, true);
fclose(f);
fprintf(summary_file,
"Simulation done.\n"
"-------------------------\n"
"Figures of merit:\n"
);
sim_results.print(summary_file, true);
double cpu_time;
boinc_calling_thread_cpu_time(cpu_time);
fprintf(summary_file,
"-------------------------\n"
"Simulator CPU time: %f secs\n"
"-------------------------\n"
"Peak FLOPS: CPU %.2fG GPU %.2fG\n",
cpu_time,
cpu_peak_flops()/1e9,
gpu_peak_flops()/1e9
);
print_project_results(summary_file);
fclose(rec_file);
make_graph("REC", "rec", 0);
}
char* next_arg(int argc, char** argv, int& i) {
if (i >= argc) {
fprintf(stderr, "Missing command-line argument\n");
usage(argv[0]);
}
return argv[i++];
}
int main(int argc, char** argv) {
int i;
char buf[256];
sim_results.clear();
for (i=1; i