diff --git a/checkin_notes b/checkin_notes index 6afd527c36..c3b61a25f7 100644 --- a/checkin_notes +++ b/checkin_notes @@ -1543,3 +1543,10 @@ Rom Feb 21 2008 curl/ +David Feb 21 2008 + - scheduler: add config option. + Use this with N=1 if your application primarily uses a coprocessor + + sched/ + sched_config.C,h + sched_send.C diff --git a/doc/spoken_languages.php b/doc/spoken_languages.php index 71123db823..ccd8792ea5 100644 --- a/doc/spoken_languages.php +++ b/doc/spoken_languages.php @@ -21,6 +21,7 @@ $spoken_languages = array( 'English', 'French', 'German', + 'Greek', 'Gujarati', 'Hausa', 'Hindi', diff --git a/html/ops/bolt_admin.php b/html/ops/bolt_admin.php index 625de7012f..e05a2c7d7b 100644 --- a/html/ops/bolt_admin.php +++ b/html/ops/bolt_admin.php @@ -4,23 +4,28 @@ require_once("../inc/bolt_db.inc"); require_once("../inc/util_ops.inc"); function show_course($course) { - echo " - Name: $course->name
Description: $course->description
Created: ".date_str($course->create_time)." - $course->doc_file - + $x = "$course->name +
Description: $course->description +
Created: ".date_str($course->create_time)." +
Course document: $course->doc_file "; + $y = "id>Course map +
id>Lesson compare +
+ "; + row2_init($x, $y); if ($course->hidden) { show_button("bolt_admin.php?action=unhide&course_id=$course->id", "Unhide", "Unhide this course"); } else { show_button("bolt_admin.php?action=hide&course_id=$course->id", "Hide", "Hide this course"); } + echo ""; } function show_courses() { $courses = BoltCourse::enum(); start_table(); - row1("Existing courses", 3); - table_header("Name/description", "Course document", ""); + table_header("Course", "Tools"); foreach ($courses as $course) { show_course($course); } @@ -30,14 +35,15 @@ function show_courses() { function add_course_form() { echo "
+ "; start_table(); row1("Add course"); - row2("Name
Visible to users
", ""); + row2("Course name
Visible to users
", ""); row2("Internal name
Not visible to users; used as a directory name, so no spaces or special chars
", ""); row2("Description
Visible to users
", ""); row2("Course document", ""); - row2("", ""); + row2("", ""); end_table(); echo "
"; } @@ -45,14 +51,16 @@ function add_course_form() { function user_settings() { global $user; $flags = $user->bolt->flags; - echo "
"; + echo " + + "; start_table(); row1("User settings"); $x = ($flags&BOLT_FLAGS_SHOW_ALL)?"checked":""; row2("Show hidden courses?", ""); $x = ($flags&BOLT_FLAGS_DEBUG)?"checked":""; row2("Show debugging output?", ""); - row2("", ""); + row2("", ""); end_table(); echo "
"; } @@ -60,18 +68,27 @@ function user_settings() { function show_all() { admin_page_head("Bolt course administration"); show_courses(); - echo "

"; - add_course_form(); - echo "

"; - user_settings(); + echo "

+ Add course +

+ User settings + "; admin_page_tail(); } $user = get_logged_in_user(); BoltUser::lookup($user); +$course_id = get_int('course_id', true); +if ($course_id) $course = BoltCourse::lookup_id($course_id); -$submit = get_str('submit', true); -if ($submit == 'Create course') { +$action = get_str('action', true); +switch ($action) { +case 'add_course_form': + admin_page_head("Add course"); + add_course_form(); + admin_page_tail(); + break; +case 'add_course': $short_name = BoltDb::escape_string(get_str('short_name')); $name = BoltDb::escape_string(get_str('course_name')); $description = BoltDb::escape_string(get_str('description')); @@ -79,36 +96,36 @@ if ($submit == 'Create course') { $now = time(); BoltCourse::insert("(create_time, short_name, name, description, doc_file) values ($now, '$short_name', '$name', '$description', '$doc_file')"); Header('Location: bolt_admin.php'); - exit(); -} else if ($submit == 'Update user') { + break; +case 'update_user_form': + admin_page_head("Bolt user settings"); + user_settings(); + admin_page_tail(); + break; +case 'update_user': $flags = 0; if (get_str('show_all', true)) $flags |= BOLT_FLAGS_SHOW_ALL; if (get_str('debug', true)) $flags |= BOLT_FLAGS_DEBUG; $user->bolt->update("flags=$flags"); $user->bolt->flags = $flags; Header('Location: bolt_admin.php'); - exit(); -} else { - $action = get_str('action', true); - if ($action) { - $course_id = get_int('course_id'); - $course = BoltCourse::lookup_id($course_id); - if (!$course) error_page("no such course"); - switch ($action) { - case 'hide': - $course->update("hidden=1"); - break; - case 'unhide': - $course->update("hidden=0"); - break; - default: - error_page("unknown action $action"); - } - Header('Location: bolt_admin.php'); - exit(); - } + break; +case 'hide': + if (!$course) error_page("no such course"); + $course->update("hidden=1"); + Header('Location: bolt_admin.php'); + break; +case 'unhide': + if (!$course) error_page("no such course"); + $course->update("hidden=0"); + Header('Location: bolt_admin.php'); + break; +case '': + show_all(); + break; +default: + error_page("unknown action $action"); } -show_all(); ?> diff --git a/sched/sched_config.C b/sched/sched_config.C index fd35e913d0..fc0f8dbd47 100644 --- a/sched/sched_config.C +++ b/sched/sched_config.C @@ -36,6 +36,10 @@ const char* CONFIG_FILE = "config.xml"; +const int MAX_NCPUS = 8; + // max multiplier for daily_result_quota and max_wus_in_progress; + // need to change as multicore processors expand + int SCHED_CONFIG::parse(FILE* f) { char tag[1024], temp[1024]; bool is_tag; @@ -51,7 +55,7 @@ int SCHED_CONFIG::parse(FILE* f) { sched_debug_level = SCHED_MSG_LOG::MSG_NORMAL; fuh_debug_level = SCHED_MSG_LOG::MSG_NORMAL; strcpy(httpd_user, "apache"); - + max_ncpus = MAX_NCPUS; if (!xp.parse_start("boinc")) return ERR_XML_PARSE; if (!xp.parse_start("config")) return ERR_XML_PARSE; @@ -141,6 +145,7 @@ int SCHED_CONFIG::parse(FILE* f) { if (xp.parse_int(tag, "file_deletion_strategy", file_deletion_strategy)) continue; if (xp.parse_bool(tag, "request_time_stats_log", request_time_stats_log)) continue; if (xp.parse_bool(tag, "enable_assignment", enable_assignment)) continue; + if (xp.parse_int(tag, "max_ncpus", max_ncpus)) continue; // don't complain about unparsed XML; // there are lots of tags the scheduler doesn't know about diff --git a/sched/sched_config.h b/sched/sched_config.h index 10dec81245..620a32eda6 100644 --- a/sched/sched_config.h +++ b/sched/sched_config.h @@ -111,6 +111,7 @@ public: // select method of automatically deleting files from host bool request_time_stats_log; bool enable_assignment; + int max_ncpus; int parse(FILE*); int parse_file(const char* dir="."); diff --git a/sched/sched_send.C b/sched/sched_send.C index f025832d29..752990908a 100644 --- a/sched/sched_send.C +++ b/sched/sched_send.C @@ -72,9 +72,13 @@ const char* infeasible_string(int code) { const int MIN_SECONDS_TO_SEND = 0; const int MAX_SECONDS_TO_SEND = (28*SECONDS_IN_DAY); -const int MAX_CPUS = 8; - // max multiplier for daily_result_quota and max_wus_in_progress; - // need to change as multicore processors expand + +inline int effective_ncpus(HOST& host) { + int ncpus = host.p_ncpus; + if (ncpus > config.max_ncpus) ncpus = config.max_ncpus; + if (ncpus < 1) ncpus = 1; + return ncpus; +} const double DEFAULT_RAM_SIZE = 64000000; // if host sends us an impossible RAM size, use this instead @@ -297,6 +301,9 @@ static int get_host_info(SCHEDULER_REPLY& reply) { double avg_turnaround = reply.host.avg_turnaround; update_average(0, 0, CREDIT_HALF_LIFE, expavg_credit, expavg_time); double credit_scale, turnaround_scale; + + // TODO: is the following still needed? Why? + // if (strstr(reply.host.os_name,"Windows") || strstr(reply.host.os_name,"Linux") ) { credit_scale = 1; @@ -306,7 +313,8 @@ static int get_host_info(SCHEDULER_REPLY& reply) { turnaround_scale = 1.25; } - if (((expavg_credit/reply.host.p_ncpus) > config.reliable_min_avg_credit*credit_scale || config.reliable_min_avg_credit == 0) + int ncpus = effective_ncpus(reply.host); + if (((expavg_credit/ncpus) > config.reliable_min_avg_credit*credit_scale || config.reliable_min_avg_credit == 0) && (avg_turnaround < config.reliable_max_avg_turnaround*turnaround_scale || config.reliable_max_avg_turnaround == 0) ){ reply.wreq.host_info.reliable = true; @@ -481,7 +489,7 @@ int wu_is_infeasible( double est_cpu = estimate_cpu_duration(wu, reply); IP_RESULT candidate("", wu.delay_bound, est_cpu); strcpy(candidate.name, wu.name); - if (check_candidate(candidate, reply.host.p_ncpus, request.ip_results)) { + if (check_candidate(candidate, effective_ncpus(reply.host), request.ip_results)) { // it passed the feasibility test, // but don't add it the the workload yet; // wait until we commit to sending it @@ -719,12 +727,7 @@ bool SCHEDULER_REPLY::work_needed(bool locality_sched) { } if (wreq.nresults >= config.max_wus_to_send) return false; - // daily quota and max jobs per host are scaled by #CPUs, - // but only up to MAX_CPUs (currently 8) - // - int ncpus = host.p_ncpus; - if (ncpus > MAX_CPUS) ncpus = MAX_CPUS; - if (ncpus < 1) ncpus = 1; + int ncpus = effective_ncpus(host); // host.max_results_day is between 1 and config.daily_result_quota inclusive // wreq.daily_result_quota is between ncpus @@ -892,7 +895,7 @@ int add_result_to_reply( } reply.insert_result(result); reply.wreq.seconds_to_fill -= wu_seconds_filled; - request.estimated_delay += wu_seconds_filled/reply.host.p_ncpus; + request.estimated_delay += wu_seconds_filled/effective_ncpus(reply.host); reply.wreq.nresults++; reply.wreq.nresults_on_host++; if (!resent_result) reply.host.nresults_today++; @@ -965,7 +968,7 @@ void send_work( if (config.workload_sim && sreq.have_other_results_list) { init_ip_results( - sreq.global_prefs.work_buf_min(), reply.host.p_ncpus, sreq.ip_results + sreq.global_prefs.work_buf_min(), effective_ncpus(reply.host), sreq.ip_results ); }