/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2021 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006-2020 Cisco Systems, Inc. All rights reserved * Copyright (c) 2011-2013 Los Alamos National Security, LLC. * All rights reserved. * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. * Copyright (c) 2014-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2021-2024 Nanook Consulting All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "prte_config.h" #include "constants.h" #include #include "src/mca/base/pmix_base.h" #include "src/mca/mca.h" #include "src/prted/pmix/pmix_server_internal.h" #include "src/util/pmix_argv.h" #include "src/util/pmix_output.h" #include "src/util/pmix_printf.h" #include "src/util/prte_cmd_line.h" #include "src/mca/errmgr/errmgr.h" #include "src/runtime/prte_globals.h" #include "src/util/pmix_show_help.h" #include "src/mca/rmaps/base/base.h" #include "src/mca/rmaps/base/rmaps_private.h" /* * The following file was created by configure. It contains extern * statements and the definition of an array of pointers to each * component's public pmix_mca_base_component_t struct. */ #include "src/mca/rmaps/base/static-components.h" /* * Global variables */ prte_rmaps_base_t prte_rmaps_base = { .selected_modules = PMIX_LIST_STATIC_INIT, .mapping = 0, .ranking = 0, .device = NULL, .inherit = false, .hwthread_cpus = false, .file = NULL, .available = NULL, .baseset = NULL, .default_mapping_policy = NULL }; /* * Local variables */ static char *rmaps_base_ranking_policy = NULL; static bool rmaps_base_inherit = false; static int prte_rmaps_base_register(pmix_mca_base_register_flag_t flags) { PRTE_HIDE_UNUSED_PARAMS(flags); /* define default mapping policy */ prte_rmaps_base.default_mapping_policy = NULL; (void) pmix_mca_base_var_register("prte", "rmaps", "default", "mapping_policy", "Default mapping Policy [slot | hwthread | core | l1cache | " "l2cache | l3cache | numa | package | node | seq | dist | ppr | " "rankfile | pe-list=a,b (comma-delimited ranges of cpus to use for this job)]," " with supported colon-delimited modifiers: PE=y (for multiple cpus/proc), " "SPAN, OVERSUBSCRIBE, NOOVERSUBSCRIBE, NOLOCAL, HWTCPUS, CORECPUS, " "DEVICE=dev (for dist policy), INHERIT, NOINHERIT, ORDERED, FILE=%s (path to file containing sequential " "or rankfile entries)", PMIX_MCA_BASE_VAR_TYPE_STRING, &prte_rmaps_base.default_mapping_policy); /* define default ranking policy */ rmaps_base_ranking_policy = NULL; (void) pmix_mca_base_var_register("prte", "rmaps", "default", "ranking_policy", "Default ranking Policy [slot | node | span | fill]", PMIX_MCA_BASE_VAR_TYPE_STRING, &rmaps_base_ranking_policy); rmaps_base_inherit = false; (void) pmix_mca_base_var_register("prte", "rmaps", "default", "inherit", "Whether child jobs shall inherit mapping/ranking/binding " "directives from their parent by default", PMIX_MCA_BASE_VAR_TYPE_BOOL, &rmaps_base_inherit); return PRTE_SUCCESS; } static int prte_rmaps_base_close(void) { pmix_list_item_t *item; /* cleanup globals */ while (NULL != (item = pmix_list_remove_first(&prte_rmaps_base.selected_modules))) { PMIX_RELEASE(item); } PMIX_DESTRUCT(&prte_rmaps_base.selected_modules); hwloc_bitmap_free(prte_rmaps_base.available); hwloc_bitmap_free(prte_rmaps_base.baseset); return pmix_mca_base_framework_components_close(&prte_rmaps_base_framework, NULL); } /** * Function for finding and opening either all MCA components, or the one * that was specifically requested via a MCA parameter. */ static int prte_rmaps_base_open(pmix_mca_base_open_flag_t flags) { int rc; /* init the globals */ PMIX_CONSTRUCT(&prte_rmaps_base.selected_modules, pmix_list_t); prte_rmaps_base.mapping = 0; prte_rmaps_base.ranking = 0; prte_rmaps_base.inherit = rmaps_base_inherit; prte_rmaps_base.hwthread_cpus = false; prte_rmaps_base.require_hwtcpus = false; prte_rmaps_base.available = hwloc_bitmap_alloc(); prte_rmaps_base.baseset = hwloc_bitmap_alloc(); /* set the default mapping and ranking policies */ if (NULL != prte_rmaps_base.default_mapping_policy) { rc = prte_rmaps_base_set_mapping_policy(NULL, prte_rmaps_base.default_mapping_policy); if (PRTE_SUCCESS != rc) { return rc; } } if (NULL != rmaps_base_ranking_policy) { rc = prte_rmaps_base_set_ranking_policy(NULL, rmaps_base_ranking_policy); if (PRTE_SUCCESS != rc) { return rc; } } /* Open up all available components */ return pmix_mca_base_framework_components_open(&prte_rmaps_base_framework, flags); } PMIX_MCA_BASE_FRAMEWORK_DECLARE(prte, rmaps, "PRTE Mapping Subsystem", prte_rmaps_base_register, prte_rmaps_base_open, prte_rmaps_base_close, prte_rmaps_base_static_components, PMIX_MCA_BASE_FRAMEWORK_FLAG_DEFAULT); PMIX_CLASS_INSTANCE(prte_rmaps_base_selected_module_t, pmix_list_item_t, NULL, NULL); static int check_modifiers(char *ck, prte_job_t *jdata, prte_mapping_policy_t *tmp) { char **ck2, *ptr; int i; uint16_t u16; bool inherit_given = false; bool noinherit_given = false; bool hwthread_cpus_given = false; bool core_cpus_given = false; bool oversubscribe_given = false; bool nooversubscribe_given = false; pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "%s rmaps:base check modifiers with %s", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), (NULL == ck) ? "NULL" : ck); if (NULL == ck) { return PRTE_SUCCESS; } ck2 = PMIX_ARGV_SPLIT_COMPAT(ck, ':'); for (i = 0; NULL != ck2[i]; i++) { if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_SPAN)) { PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_SPAN); PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_GIVEN); } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_OVERSUB)) { if (nooversubscribe_given) { /* conflicting directives */ pmix_show_help("help-prte-rmaps-base.txt", "conflicting-directives", true, "OVERSUBSCRIBE", "NOOVERSUBSCRIBE"); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } PRTE_UNSET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_NO_OVERSUBSCRIBE); PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_SUBSCRIBE_GIVEN); oversubscribe_given = true; } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_NOOVER)) { if (oversubscribe_given) { /* conflicting directives */ pmix_show_help("help-prte-rmaps-base.txt", "conflicting-directives", true, "OVERSUBSCRIBE", "NOOVERSUBSCRIBE"); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_NO_OVERSUBSCRIBE); PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_SUBSCRIBE_GIVEN); nooversubscribe_given = true; } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_NOLOCAL)) { PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_NO_USE_LOCAL); } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_ORDERED)) { if (NULL == jdata) { pmix_show_help("help-prte-rmaps-base.txt", "unsupported-default-modifier", true, "mapping policy", ck2[i]); return PRTE_ERR_SILENT; } PRTE_SET_MAPPING_DIRECTIVE(*tmp, PRTE_MAPPING_ORDERED); } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_PE)) { if (NULL == jdata) { pmix_show_help("help-prte-rmaps-base.txt", "unsupported-default-modifier", true, "mapping policy", ck2[i]); return PRTE_ERR_SILENT; } /* Numeric value must immediately follow '=' (PE=2) */ u16 = strtol(&ck2[i][3], &ptr, 10); if ('\0' != *ptr) { /* missing the value or value is invalid */ pmix_show_help("help-prte-rmaps-base.txt", "invalid-value", true, "mapping policy", "PE", ck2[i]); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } prte_set_attribute(&jdata->attributes, PRTE_JOB_PES_PER_PROC, PRTE_ATTR_GLOBAL, &u16, PMIX_UINT16); } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_INHERIT)) { if (noinherit_given) { /* conflicting directives */ pmix_show_help("help-prte-rmaps-base.txt", "conflicting-directives", true, "INHERIT", "NOINHERIT"); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } if (NULL == jdata) { prte_rmaps_base.inherit = true; } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_INHERIT, PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } inherit_given = true; } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_NOINHERIT)) { if (inherit_given) { /* conflicting directives */ pmix_show_help("help-prte-rmaps-base.txt", "conflicting-directives", true, "INHERIT", "NOINHERIT"); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } if (NULL == jdata) { prte_rmaps_base.inherit = false; } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_NOINHERIT, PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } noinherit_given = true; } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_HWTCPUS)) { if (core_cpus_given) { pmix_show_help("help-prte-rmaps-base.txt", "conflicting-directives", true, "HWTCPUS", "CORECPUS"); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } if (NULL == jdata) { prte_rmaps_base.hwthread_cpus = true; } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_HWT_CPUS, PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } hwthread_cpus_given = true; } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_CORECPUS)) { if (hwthread_cpus_given) { pmix_show_help("help-prte-rmaps-base.txt", "conflicting-directives", true, "HWTCPUS", "CORECPUS"); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } if (prte_rmaps_base.require_hwtcpus) { if (NULL == jdata) { prte_rmaps_base.hwthread_cpus = true; } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_HWT_CPUS, PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } } else { if (NULL == jdata) { prte_rmaps_base.hwthread_cpus = false; } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_CORE_CPUS, PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } } core_cpus_given = true; } else if (PMIX_CHECK_CLI_OPTION(ck2[i], PRTE_CLI_QFILE)) { if ('\0' == ck2[i][5]) { /* missing the value */ pmix_show_help("help-prte-rmaps-base.txt", "missing-value", true, "mapping policy", "FILE", ck2[i]); PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_SILENT; } if (NULL == jdata) { prte_rmaps_base.file = strdup(&ck2[i][5]); } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_FILE, PRTE_ATTR_GLOBAL, &ck2[i][5], PMIX_STRING); } } else { /* unrecognized modifier */ PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_ERR_BAD_PARAM; } } PMIX_ARGV_FREE_COMPAT(ck2); return PRTE_SUCCESS; } int prte_rmaps_base_set_default_mapping(prte_job_t *jdata, prte_rmaps_options_t *options) { prte_binding_policy_t bind; if (1 < options->cpus_per_rank) { /* assigning multiple cpus to a rank requires that we map to * objects that have multiple cpus in them, so default * to byslot if nothing else was specified by the user. */ pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "mca:rmaps mapping not given with multiple cpus/rank - using byslot"); PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); } else if (PRTE_BINDING_POLICY_IS_SET(jdata->map->binding)) { /* they specified a binding policy, but not a mapping policy, so * map by the binding object */ bind = PRTE_GET_BINDING_POLICY(jdata->map->binding); switch(bind) { case PRTE_BIND_TO_NONE: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); break; case PRTE_BIND_TO_PACKAGE: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYPACKAGE); break; case PRTE_BIND_TO_NUMA: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYNUMA); break; case PRTE_BIND_TO_L3CACHE: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYL3CACHE); break; case PRTE_BIND_TO_L2CACHE: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYL2CACHE); break; case PRTE_BIND_TO_L1CACHE: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYL1CACHE); break; case PRTE_BIND_TO_CORE: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYCORE); break; case PRTE_BIND_TO_HWTHREAD: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYHWTHREAD); break; default: PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); break; } pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "mca:rmaps mapping not given but binding set - using %s", prte_rmaps_base_print_mapping(jdata->map->mapping)); } else { if (options->nprocs <= 2) { // map by whatever CPU we are using if (options->use_hwthreads) { /* if we are using hwthread cpus, then map by those */ pmix_output_verbose(options->verbosity, options->stream, "mca:rmaps mapping not given - using byhwthread"); PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYHWTHREAD); } else { /* otherwise map by core */ pmix_output_verbose(options->verbosity, options->stream, "mca:rmaps mapping not given - using bycore"); PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYCORE); } } else { /* if package is available, map by that */ if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_PACKAGE, 0)) { pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "mca:rmaps mapping not set by user - using bypackage"); PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYPACKAGE); } else if (NULL != hwloc_get_obj_by_type(prte_hwloc_topology, HWLOC_OBJ_NUMANODE, 0)) { /* if NUMA is available, map by that */ pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "mca:rmaps mapping not set by user - using bynuma"); PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYNUMA); } else { /* if we have neither, then just do by slot */ pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "mca:rmaps mapping not given and no packages/NUMAs - using byslot"); PRTE_SET_MAPPING_POLICY(jdata->map->mapping, PRTE_MAPPING_BYSLOT); } } } return PRTE_SUCCESS; } int prte_rmaps_base_set_mapping_policy(prte_job_t *jdata, char *inspec) { char **ck, **range; char *ptr, *cptr, *val; prte_mapping_policy_t tmp; int rc, n; bool ppr = false; char *temp_token, *parm_delimiter; /* set defaults */ tmp = 0; pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "%s rmaps:base set policy with %s", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), (NULL == inspec) ? "NULL" : inspec); if (NULL == inspec) { return PRTE_SUCCESS; } /* see if a colon was included - if so, then we have a modifier */ ck = PMIX_ARGV_SPLIT_COMPAT(inspec, ':'); if (1 < PMIX_ARGV_COUNT_COMPAT(ck)) { if (0 == strcasecmp(ck[0], "ppr")) { if (4 < pmix_output_get_verbosity(prte_rmaps_base_framework.framework_output)) { pmix_asprintf(&cptr, "%s:%s", ck[1], ck[2]); pmix_output(prte_rmaps_base_framework.framework_output, "%s rmaps:base policy %s modifiers %s provided", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), ck[0], cptr); free(cptr); } /* at this point, ck contains at least * two fields (specifying the #procs/obj and the object we are * to map by). we have to allow additional modifiers here - e.g., * specifying #pe's/proc or oversubscribe - so check for modifiers. if * they are present, the rest of ck will look like "N:obj:mod1,mod2,mod3" */ if (3 > PMIX_ARGV_COUNT_COMPAT(ck)) { /* this is an error - there had to be at least one * colon to delimit the number from the object type */ pmix_show_help("help-prte-rmaps-base.txt", "invalid-pattern", true, inspec); PMIX_ARGV_FREE_COMPAT(ck); return PRTE_ERR_SILENT; } /* at this point, ck[1] contains the number of procs/resource, * ck[2] contains the string that describes * the object and ck[3] is either NULL or contains any * modifiers (i.e., "#:obj:mod1,mod2") */ if (NULL != jdata) { /* save the pattern */ pmix_asprintf(&cptr, "%s:%s", ck[1], ck[2]); prte_set_attribute(&jdata->attributes, PRTE_JOB_PPR, PRTE_ATTR_GLOBAL, cptr, PMIX_STRING); free(cptr); } PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_PPR); PRTE_SET_MAPPING_DIRECTIVE(tmp, PRTE_MAPPING_GIVEN); ppr = true; if (NULL == ck[3]) { /* there are no modifiers, so we are done */ PMIX_ARGV_FREE_COMPAT(ck); goto setpolicy; } cptr = ck[3]; } else { pmix_output_verbose(5, prte_rmaps_base_framework.framework_output, "%s rmaps:base policy %s modifiers %s provided", PRTE_NAME_PRINT(PRTE_PROC_MY_NAME), ck[0], ck[1]); cptr = ck[1]; } if (PRTE_SUCCESS != (rc = check_modifiers(cptr, jdata, &tmp)) && PRTE_ERR_TAKE_NEXT_OPTION != rc) { if (PRTE_ERR_BAD_PARAM == rc) { pmix_show_help("help-prte-rmaps-base.txt", "unrecognized-modifier", true, inspec); rc = PRTE_ERR_SILENT; } PMIX_ARGV_FREE_COMPAT(ck); return rc; } if (ppr) { /* we are done */ PMIX_ARGV_FREE_COMPAT(ck); goto setpolicy; } } /* we get here if there was only one element in * the ck array. However, if the input string * started with a ':', then there is no specified * mapping policy for us to set, but we still * have to process the modifier */ if (':' == inspec[0]) { if (PRTE_SUCCESS != (rc = check_modifiers(&inspec[1], jdata, &tmp)) && PRTE_ERR_TAKE_NEXT_OPTION != rc) { if (PRTE_ERR_BAD_PARAM == rc) { pmix_show_help("help-prte-rmaps-base.txt", "unrecognized-modifier", true, inspec); rc = PRTE_ERR_SILENT; } PMIX_ARGV_FREE_COMPAT(ck); return rc; } PMIX_ARGV_FREE_COMPAT(ck); goto setpolicy; } cptr = ck[0]; // check for an '=' and split out the value from the option if (NULL != (ptr = strchr(ck[0], '='))) { *ptr = '\0'; cptr = strdup(ck[0]); *ptr = '='; // restore the option ++ptr; if (NULL == ptr) { /* malformed option */ pmix_show_help("help-prte-rmaps-base.txt", "unrecognized-policy", true, "mapping", ck[0]); PMIX_ARGV_FREE_COMPAT(ck); free(cptr); return PRTE_ERR_SILENT; } val = strdup(ptr); } else { cptr = strdup(ck[0]); val = NULL; } if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_SLOT)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYSLOT); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_NODE)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYNODE); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_SEQ)) { /* there are several mechanisms by which the file specifying * the sequence can be passed, so not really feasible to check * it here */ PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_SEQ); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_CORE)) { if (prte_rmaps_base.require_hwtcpus) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYHWTHREAD); } else { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYCORE); } } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_L1CACHE)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYL1CACHE); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_L2CACHE)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYL2CACHE); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_L3CACHE)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYL3CACHE); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_NUMA)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYNUMA); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_PACKAGE)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYPACKAGE); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_RANKFILE)) { /* check that the file was given */ if ((NULL == jdata && NULL == prte_rmaps_base.file) || (NULL != jdata && !prte_get_attribute(&jdata->attributes, PRTE_JOB_FILE, NULL, PMIX_STRING))) { pmix_show_help("help-prte-rmaps-base.txt", "rankfile-no-filename", true); PMIX_ARGV_FREE_COMPAT(ck); free(cptr); if (NULL != val) { free(val); } return PRTE_ERR_BAD_PARAM; } /* if they asked for rankfile and didn't specify one, but did * provide one via MCA param, then use it */ if (NULL != jdata) { if (!prte_get_attribute(&jdata->attributes, PRTE_JOB_FILE, NULL, PMIX_STRING)) { if (NULL == prte_rmaps_base.file) { /* also not allowed */ pmix_show_help("help-prte-rmaps-base.txt", "rankfile-no-filename", true); PMIX_ARGV_FREE_COMPAT(ck); free(cptr); if (NULL != val) { free(val); } return PRTE_ERR_BAD_PARAM; } prte_set_attribute(&jdata->attributes, PRTE_JOB_FILE, PRTE_ATTR_GLOBAL, prte_rmaps_base.file, PMIX_STRING); } } PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYUSER); } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_HWT)) { PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_BYHWTHREAD); /* if we are mapping processes to individual hwthreads, then * we need to treat those hwthreads as separate cpus */ if (NULL == jdata) { prte_rmaps_base.hwthread_cpus = true; } else { prte_set_attribute(&jdata->attributes, PRTE_JOB_HWT_CPUS, PRTE_ATTR_GLOBAL, NULL, PMIX_BOOL); } } else if (PMIX_CHECK_CLI_OPTION(cptr, PRTE_CLI_PELIST)) { if (NULL == jdata) { pmix_show_help("help-prte-rmaps-base.txt", "unsupported-default-policy", true, "mapping", cptr); PMIX_ARGV_FREE_COMPAT(ck); free(cptr); if (NULL != val) { free(val); } return PRTE_ERR_SILENT; } if (NULL == val) { /* malformed option */ pmix_show_help("help-prte-rmaps-base.txt", "unrecognized-policy", true, "mapping", ck[0]); PMIX_ARGV_FREE_COMPAT(ck); free(cptr); if (NULL != val) { free(val); } return PRTE_ERR_SILENT; } /* Verify the list is composed of comma-delimited ranges */ temp_token = strtok(val, ","); while (NULL != temp_token) { // check for range range = PMIX_ARGV_SPLIT_COMPAT(temp_token, '-'); if (2 < PMIX_ARGV_COUNT_COMPAT(range)) { // can only have one '-' delimiter pmix_show_help("help-prte-rmaps-base.txt", "invalid-value", true, "mapping", "PE-LIST", ck[0]); PMIX_ARGV_FREE_COMPAT(ck); PMIX_ARGV_FREE_COMPAT(range); free(cptr); if (NULL != val) { free(val); } } for (n=0; NULL != range[n]; n++) { (void)strtol(range[n], &parm_delimiter, 10); if ('\0' != *parm_delimiter) { pmix_show_help("help-prte-rmaps-base.txt", "invalid-value", true, "mapping", "PE-LIST", val); PMIX_ARGV_FREE_COMPAT(ck); PMIX_ARGV_FREE_COMPAT(range); free(cptr); if (NULL != val) { free(val); } return PRTE_ERR_SILENT; } } PMIX_ARGV_FREE_COMPAT(range); temp_token = strtok(NULL, ","); } prte_set_attribute(&jdata->attributes, PRTE_JOB_CPUSET, PRTE_ATTR_GLOBAL, ptr, PMIX_STRING); PRTE_SET_MAPPING_POLICY(tmp, PRTE_MAPPING_PELIST); PRTE_SET_MAPPING_DIRECTIVE(tmp, PRTE_MAPPING_GIVEN); } else { pmix_show_help("help-prte-rmaps-base.txt", "unrecognized-policy", true, "mapping", cptr); PMIX_ARGV_FREE_COMPAT(ck); free(cptr); if (NULL != val) { free(val); } return PRTE_ERR_SILENT; } PMIX_ARGV_FREE_COMPAT(ck); free(cptr); if (NULL != val) { free(val); } PRTE_SET_MAPPING_DIRECTIVE(tmp, PRTE_MAPPING_GIVEN); setpolicy: if (NULL == jdata) { prte_rmaps_base.mapping = tmp; } else { if (NULL == jdata->map) { PRTE_ERROR_LOG(PRTE_ERR_BAD_PARAM); return PRTE_ERR_BAD_PARAM; } jdata->map->mapping = tmp; } return PRTE_SUCCESS; } int prte_rmaps_base_set_default_ranking(prte_job_t *jdata, prte_rmaps_options_t *options) { int rc; PRTE_HIDE_UNUSED_PARAMS(options); rc = prte_rmaps_base_set_ranking_policy(jdata, NULL); return rc; } int prte_rmaps_base_set_ranking_policy(prte_job_t *jdata, char *spec) { prte_ranking_policy_t tmp; prte_mapping_policy_t mapping; /* set default */ tmp = 0; if (NULL == spec) { if (NULL == jdata) { return PRTE_SUCCESS; } if (NULL == jdata->map) { jdata->map = PMIX_NEW(prte_job_map_t); } if (PRTE_RANKING_POLICY_IS_SET(jdata->map->ranking)) { return PRTE_SUCCESS; } mapping = PRTE_GET_MAPPING_POLICY(jdata->map->mapping); /* if mapping by-node, then default to rank-by node */ if (PRTE_MAPPING_BYNODE == mapping) { PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_NODE); } else if (PRTE_MAPPING_BYSLOT == mapping) { /* default to by-slot */ PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_SLOT); } else if (PRTE_MAPPING_SPAN & PRTE_GET_MAPPING_DIRECTIVE(jdata->map->mapping)) { /* default to by-span */ PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_SPAN); } else if (PRTE_MAPPING_BYHWTHREAD >= mapping && PRTE_MAPPING_BYNUMA <= mapping) { /* default to by-slot */ PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_FILL); } else { /* default to slot */ PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_SLOT); } jdata->map->ranking = tmp; return PRTE_SUCCESS; } if (PMIX_CHECK_CLI_OPTION(spec, PRTE_CLI_SLOT)) { PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_SLOT); } else if (PMIX_CHECK_CLI_OPTION(spec, PRTE_CLI_NODE)) { PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_NODE); } else if (PMIX_CHECK_CLI_OPTION(spec, PRTE_CLI_FILL)) { PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_FILL); } else if (PMIX_CHECK_CLI_OPTION(spec, PRTE_CLI_SPAN)) { PRTE_SET_RANKING_POLICY(tmp, PRTE_RANK_BY_SPAN); } else { pmix_show_help("help-prte-rmaps-base.txt", "unrecognized-policy", true, "ranking", spec); return PRTE_ERR_SILENT; } PRTE_SET_RANKING_DIRECTIVE(tmp, PRTE_RANKING_GIVEN); if (NULL == jdata) { prte_rmaps_base.ranking = tmp; } else { if (NULL == jdata->map) { jdata->map = PMIX_NEW(prte_job_map_t); } jdata->map->ranking = tmp; } return PRTE_SUCCESS; }