boinc/sched/hr_info.cpp

229 lines
6.5 KiB
C++
Raw Normal View History

// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 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 <http://www.gnu.org/licenses/>.
#ifndef _USING_FCGI_
- Added checks for net/*.h, arpa/*.h, netinet/*.h and code to figure out which of those files to include - Modified MAC address check to work on some non-Linux unixes. (mac_address.cpp) - Added suggested change to "already attached to project" checking. (ProjectInfoPage.cpp) - changed includes of standard c header files to their c++ equivalents (i.e. replaced <stdio.h> with <cstdio>) for namespace protection. - replaced "using namespace std;" with more explicit "using std::function" in several files. - Fixed bug in checking whether the os is OS/2 and added conditional OS_OS2 to the build environment. (boinc_platform.m4,configure.ac) - Changed build environment to not use -nostandardlibs unless we are using G++ and static linkage is specified. (configure.ac) - Added makefiles and package building files for solaris CSW package manager. - Fixed bug with attempting to find login name using logname. (configure.ac) - Added ifdef HAVE_* protection around some include files commonly found in sys. - Added support for unified binary for x86_64/i686-pc-solaris. (cs_platforms.cpp) - generate_host_cpid() now uses MAC address on non-linux unix. (hostinfo_network.cpp) - Macro BOINC_SET_COMPILE_FLAGS now doesn't check gcc only flags on non-gcc compilers. (boinc_set_compile_flags.m4) - Library compiles no longer depend upon the library extension or require the library to be prefixed with lib. - More fixes for fcgi builds. - Added declaration of "struct ether_addr" and ether_ntoa(). Have not yet implemented ether_ntoa() for machines that don't have it, or where it is buggy. (unix_util.h) - Added FCGI::perror() which calls FCGI_perror(). (boinc_fcgi.{h,cpp}) - Fixed library Makefiles so that all required headers get installed. svn path=/trunk/boinc/; revision=17388
2009-02-26 00:23:23 +00:00
#include <cstdio>
#else
#include "boinc_fcgi.h"
#endif
#if HAVE_MALLOC_H
#include <malloc.h>
#endif
- Added checks for net/*.h, arpa/*.h, netinet/*.h and code to figure out which of those files to include - Modified MAC address check to work on some non-Linux unixes. (mac_address.cpp) - Added suggested change to "already attached to project" checking. (ProjectInfoPage.cpp) - changed includes of standard c header files to their c++ equivalents (i.e. replaced <stdio.h> with <cstdio>) for namespace protection. - replaced "using namespace std;" with more explicit "using std::function" in several files. - Fixed bug in checking whether the os is OS/2 and added conditional OS_OS2 to the build environment. (boinc_platform.m4,configure.ac) - Changed build environment to not use -nostandardlibs unless we are using G++ and static linkage is specified. (configure.ac) - Added makefiles and package building files for solaris CSW package manager. - Fixed bug with attempting to find login name using logname. (configure.ac) - Added ifdef HAVE_* protection around some include files commonly found in sys. - Added support for unified binary for x86_64/i686-pc-solaris. (cs_platforms.cpp) - generate_host_cpid() now uses MAC address on non-linux unix. (hostinfo_network.cpp) - Macro BOINC_SET_COMPILE_FLAGS now doesn't check gcc only flags on non-gcc compilers. (boinc_set_compile_flags.m4) - Library compiles no longer depend upon the library extension or require the library to be prefixed with lib. - More fixes for fcgi builds. - Added declaration of "struct ether_addr" and ether_ntoa(). Have not yet implemented ether_ntoa() for machines that don't have it, or where it is buggy. (unix_util.h) - Added FCGI::perror() which calls FCGI_perror(). (boinc_fcgi.{h,cpp}) - Fixed library Makefiles so that all required headers get installed. svn path=/trunk/boinc/; revision=17388
2009-02-26 00:23:23 +00:00
#include <cmath>
#include "error_numbers.h"
#include "sched_msgs.h"
#include "hr_info.h"
int HR_INFO::write_file() {
int i, j;
#ifndef _USING_FCGI_
FILE* f = fopen(HR_INFO_FILENAME, "w");
#else
FCGI_FILE* f = FCGI::fopen(HR_INFO_FILENAME, "w");
#endif
if (!f) return ERR_FOPEN;
for (i=1; i<HR_NTYPES; i++) {
fprintf(f, "--------- %s ----------\n", hr_names[i]);
for (j=0; j<hr_nclasses[i]; j++) {
fprintf(f, "%d %f\n", j, rac_per_class[i][j]);
}
}
fclose(f);
return 0;
}
int HR_INFO::read_file() {
char buf[256];
#ifndef _USING_FCGI_
FILE* f = fopen(HR_INFO_FILENAME, "r");
#else
FCGI_FILE* f = FCGI::fopen(HR_INFO_FILENAME, "r");
#endif
if (!f) return ERR_FOPEN;
int i, j, jj;
double x;
for (i=1; i<HR_NTYPES; i++) {
if (!fgets(buf, sizeof(buf), f)) {
fprintf(stderr, "unexpected EOF in HR info\n");
exit(1);
}
for (j=0; j<hr_nclasses[i]; j++) {
if (!fgets(buf, sizeof(buf), f)) {
fprintf(stderr, "unexpected EOF in HR info");
exit(1);
}
int n = sscanf(buf, "%d %lf", &jj, &x);
if (n!=2 || j!=jj) {
fprintf(stderr, "bad line %s in HR info: %d; %d != %d\n", buf, n, j, jj);
exit(1);
}
rac_per_class[i][j] = x;
}
}
fclose(f);
return 0;
}
void HR_INFO::init() {
int i;
for (i=1; i<HR_NTYPES; i++) {
rac_per_class[i] = (double*) calloc(hr_nclasses[i], sizeof(double));
max_slots[i] = (int*) calloc(hr_nclasses[i], sizeof(int));
cur_slots[i] = (int*) calloc(hr_nclasses[i], sizeof(int));
}
}
void HR_INFO::scan_db() {
DB_HOST host;
int retval;
int i, n=0;
double sum=0, sum_sqr=0;
while (1) {
retval = host.enumerate("where expavg_credit>1");
if (retval) break;
if (host.p_fpops > 1e7 && host.p_fpops < 1e13) {
n++;
sum += host.p_fpops;
sum_sqr += host.p_fpops*host.p_fpops;
}
//printf("host %d: %s | %s | %s\n", host.id, host.os_name, host.p_vendor, host.p_model);
for (i=1; i<HR_NTYPES; i++) {
if (hr_unknown_class(host, i)) {
//printf("type %d: unknown\n", i);
continue;
}
int hrc = hr_class(host, i);
//printf("type %d: class %d\n", i, hrc);
if (!hrc) continue;
rac_per_class[i][hrc] += host.expavg_credit;
}
}
if (retval != ERR_DB_NOT_FOUND) {
fprintf(stderr, "host enum: %d", retval);
exit(1);
}
// if no hosts, use reasonable defaults
//
if (n) {
perf_info.host_fpops_mean = sum/n;
perf_info.host_fpops_stdev = sqrt((sum_sqr - sum*perf_info.host_fpops_mean)/n);
} else {
perf_info.host_fpops_mean = 3e9;
perf_info.host_fpops_stdev = 1e9;
}
}
void HR_INFO::allocate(int total_slots) {
int i, j;
double weight_total = 0;
for (i=1; i<HR_NTYPES; i++) {
weight_total += type_weights[i];
}
// decide how many slots to allocate to each HR type
//
for (i=1; i<HR_NTYPES; i++) {
slots_per_type[i] = (int)(total_slots*type_weights[i]/weight_total);
}
// within each type, decide how many slots to allocate to each class
//
for (i=1; i<HR_NTYPES; i++) {
int nuncom = slots_per_type[i]/2;
int ncom = slots_per_type[i] - nuncom;
log_messages.printf(MSG_DEBUG,
"type %d: %d total slots\n", i, slots_per_type[i]
);
log_messages.printf(MSG_DEBUG,
"type %d uncommitted: allocating %d slots\n", i, nuncom
);
double total_rac = 0;
for (j=1; j<hr_nclasses[i]; j++) {
total_rac += rac_per_class[i][j];
}
max_slots[i][0] = nuncom;
for (j=1; j<hr_nclasses[i]; j++) {
int n = (int)(ncom*rac_per_class[i][j]/total_rac);
// every HR class has a max of at least one,
// so that new classes can get "on the board".
// This means that the sum of the maxes can exceed the # of slots
//
if (n == 0) n = 1;
max_slots[i][j] = n;
if (n > 1) {
log_messages.printf(MSG_DEBUG,
"type %d class %d: allocating %d slots\n", i, j, n
);
}
}
for (j=0; j<hr_nclasses[i]; j++) {
cur_slots[i][j] = 0;
}
}
}
// Decide if job of the given HR type and class should be added to array,
// and if to update counts
//
bool HR_INFO::accept(int hrt, int hrc) {
if (cur_slots[hrt][hrc] >= max_slots[hrt][hrc]) {
log_messages.printf(MSG_DEBUG,
"skipping job because HR class (%d, %d) full\n", hrt, hrc
);
return false;
}
cur_slots[hrt][hrc]++;
return true;
}
void HR_INFO::show(FILE* f) {
for (int ht=1; ht<HR_NTYPES; ht++) {
fprintf(f, "HR type %s: weight %f nslots %d\n",
hr_names[ht], type_weights[ht], slots_per_type[ht]
);
for (int hc=0; hc<hr_nclasses[ht]; hc++) {
if (hc && rac_per_class[ht][hc] == 0) continue;
fprintf(f,
" class %d: rac %f max_slots %d cur_slots %d\n",
hc, rac_per_class[ht][hc], max_slots[ht][hc], cur_slots[ht][hc]
);
}
}
}
int PERF_INFO::write_file() {
#ifndef _USING_FCGI_
FILE* f = fopen(PERF_INFO_FILENAME, "w");
#else
FCGI_FILE* f = FCGI::fopen(PERF_INFO_FILENAME, "w");
#endif
if (!f) return ERR_FOPEN;
fprintf(f, "%f %f\n",
host_fpops_mean,
host_fpops_stdev
);
fclose(f);
return 0;
}