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;
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;
fprintf(html_out, "%.2f: %s%s: %.2fG ",
ninst,
colors[p->index%NCOLORS],
atp->result->rr_sim_misses_deadline?"*":"",
atp->result->name,
atp->flops_left/1e9
);
found = true;
}
if (!found) fprintf(html_out, "IDLE");
fprintf(html_out, " Jobs");
found = false;
for (i=0; i%s: %d in prog, %d done\n",
p->project_name, in_progress, done
);
found = true;
}
}
if (!found) fprintf(html_out, " ---\n");
fprintf(html_out, " | ");
}
int nproc_types = 1;
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, "BOINC client simulator
\n");
fprintf(html_out,
"Time | \n", WIDTH1
);
fprintf(html_out,
"CPU Job name and estimated time left color denotes project * means EDF mode | ", WIDTH2
);
if (coprocs.have_nvidia()) {
fprintf(html_out, "NVIDIA GPU | ", WIDTH2);
nproc_types++;
}
if (coprocs.have_ati()) {
fprintf(html_out, "ATI GPU | ", WIDTH2);
nproc_types++;
}
fprintf(html_out, "
---|
\n");
}
void html_rec() {
if (html_msg.size()) {
fprintf(html_out,
"%.0f | ",
WIDTH1, gstate.now
);
fprintf(html_out,
"%s |
\n",
nproc_types*WIDTH2,
html_msg.c_str()
);
html_msg = "";
}
fprintf(html_out, "%.0f | ", WIDTH1, gstate.now);
if (active) {
show_resource(0);
if (gpu_active) {
for (int i=1; iOFF", WIDTH2);
}
}
} else {
fprintf(html_out, "OFF | ", WIDTH2);
for (int i=1; iOFF", WIDTH2);
}
}
fprintf(html_out, "
\n");
}
void html_end() {
fprintf(html_out, "\n");
sim_results.compute();
sim_results.print(html_out);
print_project_results(html_out);
fprintf(html_out, "
\n");
fclose(html_out);
}
//#ifdef USE_REC
void set_initial_rec() {
unsigned int i;
double sum=0;
double x = total_peak_flops();
for (i=0; iresource_share;
}
for (i=0; ipwf.rec = 86400*x*(p->resource_share/sum)/1e9;
}
}
void write_recs() {
fprintf(debt_file, "%f ", gstate.now);
for (unsigned int i=0; ipwf.rec);
}
fprintf(debt_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);
}
//#else
// lines in the debt file have these fields:
// time
// per project:
// overall LTD
// CPU LTD
// CPU STD
// [NVIDIA LTD]
// [NVIDIA STD]
// [ATI LTD]
// [ATI STD]
//
void write_debts() {
fprintf(debt_file, "%f ", gstate.now);
for (unsigned int i=0; ipwf.overall_debt,
p->rsc_pwf[0].long_term_debt,
p->rsc_pwf[0].short_term_debt
);
for (int j=1; jrsc_pwf[j].long_term_debt,
p->rsc_pwf[j].short_term_debt
);
}
}
fprintf(debt_file, "\n");
}
// generate a bunch of debt graphs
//
void make_graph(const char* title, const char* fname, int field, int nfields) {
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"
"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);
}
void debt_graphs() {
int nfields = 3 + (coprocs.have_nvidia()?2:0) + (coprocs.have_ati()?2:0);
make_graph("Overall debt", "debt_overall", 0, nfields);
make_graph("CPU LTD", "debt_cpu_ltd", 1, nfields);
make_graph("CPU STD", "debt_cpu_std", 2, nfields);
if (coprocs.have_nvidia()) {
make_graph("NVIDIA LTD", "debt_nvidia_ltd", 3, nfields);
make_graph("NVIDIA STD", "debt_nvidia_std", 4, nfields);
}
if (coprocs.have_ati()) {
int off = coprocs.have_nvidia()?2:0;
make_graph("ATI LTD", "debt_ati_ltd", 3+off, nfields);
make_graph("ATI STD", "debt_ati_std", 4+off, nfields);
}
}
//#endif
static void write_inputs() {
char buf[256];
sprintf(buf, "%s/%s", outfile_prefix, INPUTS_FNAME);
FILE* f = fopen(buf, "w");
fprintf(f,
"Round-robin only: %s\n"
"scheduler EDF sim: %s\n"
"hysteresis work fetch: %s\n"
"REC-based scheduling: %s\n",
cpu_sched_rr_only?"yes":"no",
server_uses_workload?"yes":"no",
use_hyst_fetch?"yes":"no",
use_rec?"yes":"no"
);
if (use_rec) {
fprintf(f,
"REC half-life: %f\n",
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; itask_state() == PROCESS_EXECUTING) {
atp->elapsed_time += delta;
}
}
html_rec();
if (use_rec) {
write_recs();
} else {
write_debts();
}
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\n",
app->name, app->fpops_est/1e9,
app->fpops.mean/1e9, app->fpops.std_dev/1e9,
app->latency_bound,
app->weight
);
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;
if (!app->latency_bound) {
app->latency_bound = rp->report_deadline - rp->received_time;
}
}
for (i=0; iapp;
if (!app->fpops_est) {
app->fpops_est = wup->rsc_fpops_est;
}
}
for (i=0; iignore = true;
}
for (i=0; iapp->ignore = false;
}
fprintf(summary_file, "Applications and version\n");
for (j=0; jproject_name);
for (i=0; iproject != p) continue;
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 debts.
//
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; idont_request_more_work = true;
for (int j=0; jno_rsc_apps[j] = true;
}
}
for (i=0; iapp->ignore) continue;
int rt = avp->gpu_usage.rsc_type;
avp->project->no_rsc_apps[rt] = false;
}
for (i=0; iignore) {
app->project->dont_request_more_work = false;
}
}
vector::iterator iter;
iter = gstate.projects.begin();
while (iter != gstate.projects.end()) {
p = *iter;
if (p->dont_request_more_work) {
fprintf(summary_file,
"%s: Removing from simulation - no apps\n",
p->project_name
);
iter = gstate.projects.erase(iter);
} else {
iter++;
}
}
}
void do_client_simulation() {
char buf[256], buf2[256];
int retval;
sprintf(buf, "%s%s", config_prefix, CONFIG_FILE);
read_config_file(true, buf);
config.show();
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);
}
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
);
get_app_params();
cull_projects();
fprintf(summary_file, "--------------------------\n");
int j=0;
for (unsigned int i=0; iindex = j++;
}
clear_backoff();
gstate.workunits.clear();
gstate.results.clear();
gstate.set_ncpus();
work_fetch.init();
if (use_rec) {
set_initial_rec();
}
gstate.request_work_fetch("init");
simulate();
sim_results.compute();
sprintf(buf, "%s%s", outfile_prefix, RESULTS_DAT_FNAME);
FILE* 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);
fprintf(summary_file,
"-------------------------\n"
"Peak FLOPS: CPU %.2fG GPU %.2fG\n",
cpu_peak_flops()/1e9,
gpu_peak_flops()/1e9
);
print_project_results(summary_file);
if (use_rec) {
make_graph("REC", "rec", 0);
} else {
debt_graphs();
}
}
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, retval;
char buf[256];
sim_results.clear();
for (i=1; i