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 | GFLOPs left | %s \n",
rsc_type?"GPU | ":""
);
}
if (rsc_type) {
sprintf(buf, "%d | ", rp->coproc_indices[0]);
} else {
strcpy(buf, "");
}
fprintf(html_out, "%.2f | %s%s | %.0f | %s \n",
ninst,
colors[p->index%NCOLORS],
rp->rr_sim_misses_deadline?"*":"",
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, "
| ");
}
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,
"\n"
"BOINC client emulator results
\n"
);
show_project_colors();
fprintf(html_out,
"Time | \n", WIDTH1
);
fprintf(html_out,
"CPU | ", 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,
"%s | ",
WIDTH1, sim_time_string(gstate.now)
);
fprintf(html_out,
"%s |
\n",
nproc_types*WIDTH2,
html_msg.c_str()
);
html_msg = "";
}
fprintf(html_out, "%s | ", WIDTH1, sim_time_string(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_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 = 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);
}
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"
"hysteresis work fetch: %s\n",
existing_jobs_only?"yes":"no",
cpu_sched_rr_only?"yes":"no",
server_uses_workload?"yes":"no",
use_hyst_fetch?"yes":"no"
);
fprintf(f,
"REC half-life: %f\n", 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; 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\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;
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 missing app params, fill in defaults
//
if (!app->fpops_est) {
app->fpops_est = 3600e9;
}
if (!app->latency_bound) {
app->latency_bound = 86400;
}
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; ino_apps = 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->no_apps = false;
}
}
vector::iterator iter;
iter = gstate.projects.begin();
while (iter != gstate.projects.end()) {
p = *iter;
if (p->no_apps) {
fprintf(summary_file,
"%s: Removing from simulation - no apps\n",
p->project_name
);
iter = gstate.projects.erase(iter);
} else if (p->non_cpu_intensive) {
fprintf(summary_file,
"%s: Removing from simulation - non CPU intensive\n",
p->project_name
);
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);
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);
}
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");
}
}
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
//
for (int i=0; iindex = j++;
}
clear_backoff();
gstate.log_show_projects();
gstate.set_ncpus();
work_fetch.init();
//set_initial_rec();
debt_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(debt_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, retval;
char buf[256];
sim_results.clear();
for (i=1; i