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
}
Example #2
0
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
}
Example #3
0
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
}