func job_verification_function() { // // Prevent jobs from accidental oversubscription // const intel_slots, amd_slots = 16, 64 var modified_p bool = false if !jsv.JSV_is_param("pe_name") { jsv.JSV_set_param("binding_strategy", "linear_automatic") jsv.JSV_set_param("binding_type", "set") jsv.JSV_set_param("binding_amount", "1") jsv.JSV_set_param("binding_exp_n", "0") modified_p = true } else { hostlist, _ := jsv.JSV_get_param("q_hard") hostlist = strings.SplitAfterN(hostlist, "@", 2)[1] v, _ := jsv.JSV_get_param("pe_max") pe_max, _ := strconv.Atoi(v) if strings.EqualFold("@amdhosts", hostlist) { if pe_max > 127 { jsv.JSV_set_param("R", "y") modified_p = true } } if strings.EqualFold("@intelhosts", hostlist) { if pe_max > 31 { jsv.JSV_set_param("R", "y") modified_p = true } } } if modified_p { // jsv.JSV_show_params() jsv.JSV_correct("Job was modified") } else { jsv.JSV_correct("Job was not modified") } return }
func job_verification_function() { job_id, _ := jsv.JSV_get_param("JOB_ID") if context, exists := jsv.JSV_get_param("ac"); exists == false || context != "jsv" { jsv.JSV_accept("Job was accepted") return } // For certain queues we don't want the JSV to take effect queues_to_ignore := regexp.MustCompile(`admin.q.*`) if queue, exists := jsv.JSV_get_param("q_hard"); exists && queues_to_ignore.MatchString(queue) == true { jsv.JSV_accept("Job was accepted") return } // Can be used for displaying submission parameters and // submission environment variables. //jsv.JSV_log_info("--------------- Initial Params -----------------") //jsv.JSV_show_params() //jsv.JSV_log_info("------------------------------------------------") // Automatic Core Binding // ----------------------------------------------------------------------------------------------------- // Check if any binding has been already defined by the user. // If nothing has been set, and the user is in one of the defined parallel environments // then set an automatic linear core-binding set to the (min) number of slots requested if binding_type, binding_exists := jsv.JSV_get_param("binding_type"); binding_exists { jsv.JSV_log_info(fmt.Sprintf("Binding type: %s already set. No automatic core binding", binding_type)) } else if pe_name, pe_exists := jsv.JSV_get_param("pe_name"); pe_exists { // Compile regex to match all PEs that we want to do automatic // core-binding on validPE := regexp.MustCompile(`^(openmp|smp)$`) if validPE.MatchString(pe_name) { pe_min, _ := jsv.JSV_get_param("pe_min") slots := pe_min jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Parallel Env: %s qualifies for automatic core binding", job_id, pe_name)) // setting -binding linear:slots to each job binding the job to the same number of cores as slots jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Setting automatic core binding to: %s cores", job_id, slots)) jsv.JSV_set_param("binding_strategy", "linear_automatic") jsv.JSV_set_param("binding_type", "set") jsv.JSV_set_param("binding_amount", slots) jsv.JSV_set_param("binding_exp_n", "0") } else { jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Parallel Env: %s does not qualify for automatic core binding", job_id, pe_name)) } } else { // No parallel environment set. So bind to 1 core only. // setting -binding linear:1 to each job (so that each // job can only use one core on the compute node) jsv.JSV_log_info(fmt.Sprintf("Job ID: %s. Setting automatic core binding to: %s cores", job_id, "1")) jsv.JSV_set_param("binding_strategy", "linear_automatic") jsv.JSV_set_param("binding_type", "set") jsv.JSV_set_param("binding_amount", "1") jsv.JSV_set_param("binding_exp_n", "0") } // Automatic Memory Limitation // ----------------------------------------------------------------------------------------------------- // Check if any memory limit has been set by the user. // If nothing has been set, define a memory limit as a multiple of the number of slots requested. // Use hard-coded value of 2GiB*slots. // const memory_per_slot int = 2048 // if memory, exists := jsv.JSV_sub_get_param("l_hard", "m_mem_free"); exists { // jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Memory limit of: %s already set. No automatic memory limiting", job_id, memory)) // } else { // // convert slots to an integer, then calculate memory limit // if num_slots, err := strconv.Atoi(slots); err == nil { // memory_limit := num_slots * memory_per_slot // jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Setting automatic memory limit of: %d MiB", job_id, memory_limit)) // jsv.JSV_sub_add_param("l_hard", "m_mem_free", strconv.Itoa(memory_limit)+"M") // } else { // jsv.JSV_log_error(fmt.Sprintf("Unable to convert: %s to an integer. Unable to set memory limit", slots)) // } // } // Time Limitation // if h_rt, exists := jsv.JSV_sub_get_param("l_hard", "h_rt"); exists { // jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Time limit of: %s already set. No automatic time limiting", job_id, h_rt)) // } else if h_rt, exists := jsv.JSV_sub_get_param("l_hard", "{~}h_rt"); exists { // jsv.JSV_log_info(fmt.Sprintf("Job ID: %s Time limit of: %s already set. No automatic time limiting", job_id, h_rt)) // } else { // jsv.JSV_reject("No job time limit set. Please either set a time limit or choose a job class from: default, default.medium, default.long") // return // } // accepting the job but indicating that we did // some changes //jsv.JSV_log_info("--------------- Final Params -----------------") //jsv.JSV_show_params() //jsv.JSV_log_info("------------------------------------------------") jsv.JSV_correct("Job was modified") return }
func job_verification_function() { // // Prevent jobs from accidental oversubscription // // NOTE // The submit(1) man page has slightly different terminology: // "binding_instance" in the man page is "binding_type" in // the jsv library. const intel_slots, amd_slots = 16, 64 var modified_p bool = false group, _ := jsv.JSV_get_param("GROUP") if !jsv.JSV_is_param("pe_name") { // no PE => serial job jsv.JSV_set_param("binding_strategy", "linear_automatic") jsv.JSV_set_param("binding_amount", "1") jsv.JSV_set_param("binding_type", "set") jsv.JSV_set_param("binding_exp_n", "0") modified_p = true } else { // parallel job if !jsv.JSV_is_param("binding_strategy") { pe_name, _ := jsv.JSV_get_param("pe_name") var v string v, _ = jsv.JSV_get_param("pe_max") pe_max, _ := strconv.Atoi(v) v, _ = jsv.JSV_get_param("pe_min") pe_min, _ := strconv.Atoi(v) if strings.EqualFold("shm", pe_name) && (pe_max == pe_min) { jsv.JSV_set_param("binding_strategy", "linear_automatic") jsv.JSV_set_param("binding_type", "pe") jsv.JSV_set_param("binding_amount", strconv.Itoa(pe_max)) modified_p = true } else { l_hard, _ := jsv.JSV_get_param("l_hard") q_hard, _ := jsv.JSV_get_param("q_hard") singleat_re, _ := regexp.Compile("@[a-z]") doubleat_re, _ := regexp.Compile("@@") intelhost_re, _ := regexp.Compile("^ic[:digit:]{2}n[:digit:]{2}$") amdhost_re, _ := regexp.Compile("^ac[:digit:]{2}n[:digit:]{2}$") gpuhost_re, _ := regexp.Compile("^gpu[:digit:]{2}$") var q string var host string var hostlist string if singleat_re.MatchString(q_hard) { // we have a single host q = strings.Split(q_hard, "@")[0] host = strings.Split(q_hard, "@")[1] } else if doubleat_re.MatchString(q_hard) { // we have a hostgroup q = strings.Split(q_hard, "@")[0] hostlist = strings.SplitAfterN(q_hard, "@", 2)[1] } else { // we have no host specifier q = q_hard } cplx := make(map[string]string) l_hard_split := strings.Split(l_hard, ",") for _, v := range l_hard_split { cplx[strings.Split(v, "=")[0]] = strings.Split(v, "=")[1] } vendor, ok := cplx["vendor"] if !ok { // vendor was not requested by job if strings.EqualFold("gpu.q", q) || strings.EqualFold("@intelhosts", hostlist) { vendor = "intel" } else if strings.EqualFold("@amdhosts", hostlist) { vendor = "amd" } else if len(host) != 0 { // specific hosts requested if intelhost_re.MatchString(host) || gpuhost_re.MatchString(host) { vendor = "intel" } else if amdhost_re.MatchString(host) { vendor = "amd" } } else { _, ok = cplx["ngpus"] if !ok { _, ok = cplx["cuda"] } if ok { vendor = "intel" } else { vendor = "undef" } } } // Only specify binding if pe_max == pe_min, i.e. if a fixed // number of slots is requested if !strings.EqualFold("undef", vendor) && pe_max == pe_min { jsv.JSV_set_param("binding_strategy", "linear_automatic") jsv.JSV_set_param("binding_type", "pe") // Don't do reservation for high-throughput groups if !strings.EqualFold("rosenGrp", group) { if strings.EqualFold("intel", vendor) { if pe_max < intel_slots { jsv.JSV_set_param("binding_amount", strconv.Itoa(pe_max)) } else { jsv.JSV_set_param("binding_amount", strconv.Itoa(intel_slots)) } if pe_max > 31 { jsv.JSV_set_param("R", "y") } } else if strings.EqualFold("amd", vendor) { if pe_max < amd_slots { jsv.JSV_set_param("binding_amount", strconv.Itoa(pe_max)) } else { jsv.JSV_set_param("binding_amount", strconv.Itoa(amd_slots)) if pe_max > 127 { jsv.JSV_set_param("R", "y") } } } } modified_p = true } } } } // XXX print out debugging info - comment out for production jsv.JSV_show_params() if modified_p { jsv.JSV_correct("Job was modified") } else { jsv.JSV_correct("Job was not modified") } return }