diff --git a/sched/plan_class_spec.cpp b/sched/plan_class_spec.cpp index 53e652e32fc..aa64523f5a0 100644 --- a/sched/plan_class_spec.cpp +++ b/sched/plan_class_spec.cpp @@ -152,12 +152,41 @@ bool PLAN_CLASS_SPEC::opencl_check(OPENCL_DEVICE_PROP& opencl_prop) { return true; } -bool PLAN_CLASS_SPEC::check(SCHEDULER_REQUEST& sreq, HOST_USAGE& hu) { +bool PLAN_CLASS_SPEC::check(SCHEDULER_REQUEST& sreq, HOST_USAGE& hu, const WORKUNIT* wu) { COPROC* cpp = NULL; bool can_use_multicore = true; hu.sequential_app(sreq.host.p_fpops); + // disabled by configuration + if (disabled) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] Plan class disabled\n"); + return false; + } + + // WU restriction + if (min_wu_id && wu->id < min_wu_id) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too old\n", wu->id); + return false; + } + if (max_wu_id && wu->id > max_wu_id) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too new\n", wu->id); + return false; + } + if (min_batch && wu->batch < min_batch) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too old\n", wu->id); + return false; + } + if (max_batch && wu->batch > max_batch) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too new\n", wu->id); + return false; + } + // CPU features // // older clients report CPU features in p_model, @@ -882,19 +911,47 @@ bool PLAN_CLASS_SPEC::check(SCHEDULER_REQUEST& sreq, HOST_USAGE& hu) { } - bool PLAN_CLASS_SPECS::check( - SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu + SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu, const WORKUNIT* wu ) { for (unsigned int i=0; iid < classes[i].min_wu_id) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too old for plan class '%s'\n", wu->id, plan_class); + return true; + } + if (classes[i].max_wu_id && wu->id > classes[i].max_wu_id) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too new for plan class '%s'\n", wu->id, plan_class); + return true; + } + if (classes[i].min_batch && wu->batch < classes[i].min_batch) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too old for plan class '%s'\n", wu->id, plan_class); + return true; + } + if (classes[i].max_batch && wu->batch > classes[i].max_batch) { + if (config.debug_version_select) + log_messages.printf(MSG_NORMAL, "[version] WU#%ld too new for plan class '%s'\n", wu->id, plan_class); + return true; + } + break; + } + } + return false; +} + int PLAN_CLASS_SPEC::parse(XML_PARSER& xp) { char buf[256]; int i; @@ -903,6 +960,7 @@ int PLAN_CLASS_SPEC::parse(XML_PARSER& xp) { return 0; } if (xp.parse_str("name", name, sizeof(name))) continue; + if (xp.parse_bool("disabled", disabled)) continue; if (xp.parse_int("min_core_client_version", min_core_client_version)) continue; if (xp.parse_int("max_core_client_version", max_core_client_version)) continue; if (xp.parse_str("gpu_type", gpu_type, sizeof(gpu_type))) continue; @@ -975,6 +1033,10 @@ int PLAN_CLASS_SPEC::parse(XML_PARSER& xp) { if (xp.parse_int("min_driver_version", min_driver_version)) continue; if (xp.parse_int("max_driver_version", max_driver_version)) continue; if (xp.parse_str("gpu_utilization_tag", gpu_utilization_tag, sizeof(gpu_utilization_tag))) continue; + if (xp.parse_int("min_wu_id", min_wu_id)) continue; + if (xp.parse_int("max_wu_id", max_wu_id)) continue; + if (xp.parse_int("min_batch", min_batch)) continue; + if (xp.parse_int("max_batch", max_batch)) continue; if (xp.parse_bool("need_ati_libs", need_ati_libs)) continue; if (xp.parse_bool("need_amd_libs", need_amd_libs)) continue; diff --git a/sched/plan_class_spec.h b/sched/plan_class_spec.h index aae097b9415..85fbb8a082a 100644 --- a/sched/plan_class_spec.h +++ b/sched/plan_class_spec.h @@ -26,6 +26,7 @@ // if you add anything here, initialize if in the constructor // struct PLAN_CLASS_SPEC { + bool disabled; char name[256]; char gpu_type[256]; bool cuda; @@ -59,6 +60,10 @@ struct PLAN_CLASS_SPEC { // for non-compute-intensive, or override for GPU apps bool have_host_summary_regex; regex_t host_summary_regex; + int min_wu_id; + int max_wu_id; + int min_batch; + int max_batch; // GPU apps // @@ -109,7 +114,7 @@ struct PLAN_CLASS_SPEC { int parse(XML_PARSER&); bool opencl_check(OPENCL_DEVICE_PROP&); - bool check(SCHEDULER_REQUEST& sreq, HOST_USAGE& hu); + bool check(SCHEDULER_REQUEST& sreq, HOST_USAGE& hu, const WORKUNIT* wu); PLAN_CLASS_SPEC(); }; @@ -117,6 +122,7 @@ struct PLAN_CLASS_SPECS { std::vector classes; int parse_file(const char*); int parse_specs(FILE*); - bool check(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu); + bool check(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu, const WORKUNIT* wu); + bool wu_is_infeasible(char* plan_class, const WORKUNIT* wu); PLAN_CLASS_SPECS(){}; }; diff --git a/sched/sched_customize.cpp b/sched/sched_customize.cpp index a2a7e681d52..fbece6521c1 100644 --- a/sched/sched_customize.cpp +++ b/sched/sched_customize.cpp @@ -92,12 +92,14 @@ using std::string; #define OPENCL_NVIDIA_MIN_RAM CUDA_MIN_RAM #endif +PLAN_CLASS_SPECS plan_class_specs; + GPU_REQUIREMENTS gpu_requirements[NPROC_TYPES]; bool wu_is_infeasible_custom( - WORKUNIT& /*wu*/, + WORKUNIT& wu, APP& /*app*/, - BEST_APP_VERSION& /*bav*/ + BEST_APP_VERSION& bav ) { #if 0 // example 1: if WU name contains "_v1", don't use GPU apps. @@ -129,6 +131,14 @@ bool wu_is_infeasible_custom( return true; } #endif + + // WU restriction + if (plan_class_specs.classes.size() > 0) { + if (plan_class_specs.wu_is_infeasible(bav.avp->plan_class, &wu)) { + return true; + } + } + return false; } @@ -912,12 +922,10 @@ static inline bool app_plan_vbox( return true; } -PLAN_CLASS_SPECS plan_class_specs; - // app planning function. // See http://boinc.berkeley.edu/trac/wiki/AppPlan // -bool app_plan(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu) { +bool app_plan(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu, const WORKUNIT* wu) { char buf[256]; static bool check_plan_class_spec = true; static bool have_plan_class_spec = false; @@ -955,7 +963,7 @@ bool app_plan(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu) { return false; } if (have_plan_class_spec) { - return plan_class_specs.check(sreq, plan_class, hu); + return plan_class_specs.check(sreq, plan_class, hu, wu); } if (!strcmp(plan_class, "mt")) { diff --git a/sched/sched_customize.h b/sched/sched_customize.h index b9ec20277f6..e1c0ec6d0db 100644 --- a/sched/sched_customize.h +++ b/sched/sched_customize.h @@ -88,7 +88,7 @@ struct GPU_REQUIREMENTS { extern GPU_REQUIREMENTS gpu_requirements[NPROC_TYPES]; extern bool wu_is_infeasible_custom(WORKUNIT&, APP&, BEST_APP_VERSION&); -extern bool app_plan(SCHEDULER_REQUEST&, char* plan_class, HOST_USAGE&); +extern bool app_plan(SCHEDULER_REQUEST&, char* plan_class, HOST_USAGE&, const WORKUNIT* wu); extern void handle_file_xfer_results(); // Suppose we have a computation that uses two devices alternately. diff --git a/sched/sched_version.cpp b/sched/sched_version.cpp index bc9559eecef..c99df5cfa3d 100644 --- a/sched/sched_version.cpp +++ b/sched/sched_version.cpp @@ -498,7 +498,7 @@ static BEST_APP_VERSION* check_homogeneous_app_version( // and see if it supports the plan class // if (strlen(avp->plan_class)) { - if (!app_plan(*g_request, avp->plan_class, bav.host_usage)) { + if (!app_plan(*g_request, avp->plan_class, bav.host_usage, &wu)) { return NULL; } } else { @@ -705,7 +705,7 @@ BEST_APP_VERSION* get_app_version( } if (strlen(av.plan_class)) { - if (!app_plan(*g_request, av.plan_class, host_usage)) { + if (!app_plan(*g_request, av.plan_class, host_usage, &wu)) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, "[version] [AV#%lu] app_plan() returned false\n",