From 76e3925b9806dab013ba5b2ef2c92a0a5df1eec8 Mon Sep 17 00:00:00 2001 From: Morris Jette <jette@schedmd.com> Date: Thu, 22 May 2014 16:17:07 -0700 Subject: [PATCH] preempt/job_prio _add CHECK_FOR_PREEMPTOR_OVERALLOC --- .../preempt/job_prio/preempt_job_prio.c | 115 +++++++++++++++++- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/src/plugins/preempt/job_prio/preempt_job_prio.c b/src/plugins/preempt/job_prio/preempt_job_prio.c index 186fdc5658d..7ffe2095bf3 100644 --- a/src/plugins/preempt/job_prio/preempt_job_prio.c +++ b/src/plugins/preempt/job_prio/preempt_job_prio.c @@ -73,8 +73,8 @@ /* If the #define options listed below for CHECK_FOR_PREEMPTOR_OVERALLOC and * CHECK_FOR_ACCOUNT_UNDERALLOC are commented out, this plugin will work as a * simple job priority based preemption plugin. */ -#define CHECK_FOR_PREEMPTOR_OVERALLOC 0 -#define CHECK_FOR_ACCOUNT_UNDERALLOC 0 +#define CHECK_FOR_PREEMPTOR_OVERALLOC 1 +#define CHECK_FOR_ACCOUNT_UNDERALLOC 1 const char plugin_name[] = "Preempt by Job Priority and Runtime"; const char plugin_type[] = "preempt/job_prio"; @@ -92,6 +92,111 @@ typedef struct /*****End of plugin specific declarations**********************************/ +/* Check accounts associated with these two jobs, return true if preemptor job + * can preempt preeemptee. This is done by checking if the preemptee account + * name contains an _p or not...) + * Also, check if Preemptors QoS is higher or lower than that of the preemptee. + * If QOS is the same of lower and they are from the same account, then this + * is NOT a candidate. */ +static bool _account_preemptable(struct job_record *preemptor_job_ptr, + struct job_record *preemptee_job_ptr) +{ + slurmdb_association_rec_t *preemptor_assoc, *preemptee_assoc; + slurmdb_qos_rec_t *preemptor_qos, *preemptee_qos; + bool is_from_same_account = false; + int i; + + preemptor_assoc = + (slurmdb_association_rec_t *)preemptor_job_ptr->assoc_ptr; + preemptee_assoc = + (slurmdb_association_rec_t *)preemptee_job_ptr->assoc_ptr; + if (!preemptor_assoc || !preemptee_assoc) + return false; + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("%s: Preemptor JobID %u account %s, preemptee " + "JobID %u account %s", + plugin_type, + preemptor_job_ptr->job_id, preemptor_assoc->acct, + preemptee_job_ptr->job_id, preemptee_assoc->acct); + } + + preemptor_qos = preemptor_job_ptr->qos_ptr; + preemptee_qos = preemptee_job_ptr->qos_ptr; + if (!preemptor_qos || !preemptee_qos) + return false; + + if (!strcmp(preemptor_assoc->acct, preemptee_assoc->acct)) { + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("%s: Preemptor and preemptee share account = %s", + plugin_type, preemptee_assoc->acct); + } + + if (preemptor_qos->priority <= preemptee_qos->priority) { + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("%s: Preemptor(%u, %s, QoS(%s)=%u) and " + "preemptee(%u, %s, QOS(%s)=%u) share " + "share account, but QOS1 <= QOS2", + plugin_type, preemptor_job_ptr->job_id, + preemptor_job_ptr->name, + preemptor_qos->name, + preemptor_qos->priority, + preemptee_job_ptr->job_id, + preemptee_job_ptr->name, + preemptee_qos->name, + preemptee_qos->priority); + } + /* Same association but lower or same QoS Priority. + * This is not a candidate. */ + return false; + } + + /* This is a candidate from the same account as the preemptor... + * Preempting this job will have an impact as far as whether + * the account will become overallocated. */ + is_from_same_account = true; + } + + i = strlen(preemptee_assoc->acct); + if (!strncmp(((preemptee_assoc->acct) + i - 3), "_np", 3)) { + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("%s: Preemptee is skipped, NON-PREEMPTABLE " + "(ending with NP) account %s", + plugin_type, preemptee_assoc->acct); + } + return false; + } + + /* Check to see if the preemptee's account is currently using more than + * its share. If the account is using more than its share, then this + * job is a candidate. If not, it is NOT a candidate. */ + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("Preemptor(%u) USEDCPUs:%u SHARES: %f CL_CPU %u TOT: %f", + preemptor_job_ptr->job_id, + preemptee_assoc->usage->grp_used_cpus, + preemptee_assoc->usage->shares_norm, + preemptor_job_ptr->part_ptr->total_cpus, + (preemptor_job_ptr->part_ptr->total_cpus* + preemptee_assoc->usage->shares_norm)); + } + + if ((preemptee_assoc->usage->grp_used_cpus > + preemptee_assoc->usage->shares_norm * + preemptee_job_ptr->part_ptr->total_cpus) || is_from_same_account) { + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("Preemptee(%u) acccount %s already overallocated", + preemptee_job_ptr->job_id, preemptee_assoc->acct); + } + } else { + if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { + info("Preemptee(%u) acccount %s not overallocated, skip", + preemptee_job_ptr->job_id, preemptee_assoc->acct); + } + return false; + } + + return true; +} + /* Destroy a acct_usage_element data structure element. */ static void _destroy_acct_usage_element(void *object) { @@ -417,7 +522,7 @@ extern List find_preemptable_jobs(struct job_record *job_ptr) if (slurm_get_debug_flags() & DEBUG_FLAG_PRIO) { info("%s: Looking for jobs to preempt for JobId %u", - plugin_type, preemptor_job_ptr->job_id); + plugin_type, preemptor_job_ptr->job_id); } /* Build an array of pointers to preemption candidates */ @@ -438,6 +543,10 @@ extern List find_preemptable_jobs(struct job_record *job_ptr) preemptee_job_ptr->job_id)) continue; + if (CHECK_FOR_PREEMPTOR_OVERALLOC && + !_account_preemptable(preemptor_job_ptr, preemptee_job_ptr)) + continue; + /* This job is a valid preemption candidate and should be added * to the list. Create the list as needed. */ if (preemptee_job_list == NULL) -- GitLab