root/ompi/mpiext/affinity/c/mpiext_affinity_str.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. OMPI_Affinity_str
  2. get_rsrc_ompi_bound
  3. get_rsrc_current_binding
  4. get_rsrc_exists
  5. get_layout_ompi_bound
  6. get_layout_current_binding
  7. get_layout_exists

   1 /*
   2  * Copyright (c) 2004-2009 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2010-2018 Cisco Systems, Inc.  All rights reserved
   6  * Copyright (c) 2010      Oracle and/or its affiliates.  All rights reserved.
   7  * Copyright (c) 2012      Los Alamos National Security, LLC.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2015-2017 Research Organization for Information Science
  10  *                         and Technology (RIST). All rights reserved.
  11  * Copyright (c) 2015-2017 Intel, Inc. All rights reserved.
  12  * $COPYRIGHT$
  13  *
  14  * Additional copyrights may follow
  15  *
  16  * $HEADER$
  17  *
  18  * Simple routine to expose three things to the MPI process:
  19  *
  20  * 1. What processor(s) Open MPI bound this process to
  21  * 2. What processor(s) this process is bound to
  22  * 3. What processor(s) exist on this host
  23  *
  24  * Note that 1 and 2 may be different!
  25  */
  26 
  27 #include "ompi_config.h"
  28 
  29 #include <stdio.h>
  30 #include <string.h>
  31 
  32 #include "opal/mca/hwloc/base/base.h"
  33 #include "opal/runtime/opal.h"
  34 #include "opal/util/string_copy.h"
  35 
  36 #include "ompi/communicator/communicator.h"
  37 #include "ompi/errhandler/errhandler.h"
  38 #include "ompi/mca/rte/rte.h"
  39 #include "ompi/mpi/c/bindings.h"
  40 #include "ompi/mpiext/affinity/c/mpiext_affinity_c.h"
  41 
  42 static const char FUNC_NAME[] = "OMPI_Affinity";
  43 static const char ompi_nobind_str[] = "Open MPI did not bind this process";
  44 static const char not_bound_str[] = "Not bound (i.e., bound to all processors)";
  45 
  46 
  47 static int get_rsrc_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX]);
  48 static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX]);
  49 static int get_rsrc_exists(char str[OMPI_AFFINITY_STRING_MAX]);
  50 static int get_layout_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX]);
  51 static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX]);
  52 static int get_layout_exists(char str[OMPI_AFFINITY_STRING_MAX]);
  53 
  54 
  55 int OMPI_Affinity_str(ompi_affinity_fmt_t fmt_type,
  56                       char ompi_bound[OMPI_AFFINITY_STRING_MAX],
  57                       char current_binding[OMPI_AFFINITY_STRING_MAX],
  58                       char exists[OMPI_AFFINITY_STRING_MAX])
  59 {
  60     int ret;
  61 
  62     memset(ompi_bound, 0, OMPI_AFFINITY_STRING_MAX);
  63     memset(current_binding, 0, OMPI_AFFINITY_STRING_MAX);
  64     memset(exists, 0, OMPI_AFFINITY_STRING_MAX);
  65 
  66     /* If we have no hwloc support, return nothing */
  67     if (NULL == opal_hwloc_topology) {
  68         return MPI_SUCCESS;
  69     }
  70 
  71     /* Otherwise, return useful information */
  72     switch (fmt_type) {
  73     case OMPI_AFFINITY_RSRC_STRING_FMT:
  74     if (OMPI_SUCCESS != (ret = get_rsrc_ompi_bound(ompi_bound)) ||
  75         OMPI_SUCCESS != (ret = get_rsrc_current_binding(current_binding)) ||
  76         OMPI_SUCCESS != (ret = get_rsrc_exists(exists))) {
  77         return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, ret, FUNC_NAME);
  78     }
  79     break;
  80     case OMPI_AFFINITY_LAYOUT_FMT:
  81     if (OMPI_SUCCESS != (ret = get_layout_ompi_bound(ompi_bound)) ||
  82         OMPI_SUCCESS != (ret = get_layout_current_binding(current_binding)) ||
  83         OMPI_SUCCESS != (ret = get_layout_exists(exists))) {
  84         return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, ret, FUNC_NAME);
  85     }
  86     break;
  87     default:
  88     return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG, FUNC_NAME);
  89     }
  90 
  91     return MPI_SUCCESS;
  92 }
  93 
  94 /*---------------------------------------------------------------------------*/
  95 
  96 /*
  97  * Where did OMPI bind this process? (prettyprint)
  98  */
  99 static int get_rsrc_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
 100 {
 101     int ret;
 102 
 103     /* If OMPI did not bind, indicate that */
 104     if (!ompi_rte_proc_is_bound) {
 105         opal_string_copy(str, ompi_nobind_str, OMPI_AFFINITY_STRING_MAX);
 106         return OMPI_SUCCESS;
 107     }
 108 
 109     if (NULL == ompi_proc_applied_binding) {
 110         ret = OPAL_ERR_NOT_BOUND;
 111     } else {
 112         ret = opal_hwloc_base_cset2str(str, OMPI_AFFINITY_STRING_MAX,
 113                                        opal_hwloc_topology,
 114                                        ompi_proc_applied_binding);
 115     }
 116     if (OPAL_ERR_NOT_BOUND == ret) {
 117         opal_string_copy(str, not_bound_str, OMPI_AFFINITY_STRING_MAX);
 118         ret = OMPI_SUCCESS;
 119     }
 120     return ret;
 121 }
 122 
 123 
 124 /*
 125  * Where is this process currently bound? (prettyprint)
 126  */
 127 static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
 128 {
 129     int ret;
 130     hwloc_obj_t root;
 131     hwloc_cpuset_t boundset, rootset;
 132     bool bound = false;
 133 
 134     /* get our root object */
 135     root = hwloc_get_root_obj(opal_hwloc_topology);
 136     rootset = root->cpuset;
 137 
 138     /* get our bindings */
 139     boundset = hwloc_bitmap_alloc();
 140     if (hwloc_get_cpubind(opal_hwloc_topology, boundset,
 141                           HWLOC_CPUBIND_PROCESS) < 0) {
 142         /* we are NOT bound if get_cpubind fails, nor can we be bound
 143            - the environment does not support it */
 144         bound = false;
 145     } else {
 146         /* we are bound if the two cpusets are not equal, or if there
 147            is only ONE PU available to us */
 148         if (0 != hwloc_bitmap_compare(boundset, rootset) ||
 149             opal_hwloc_base_single_cpu(rootset) ||
 150             opal_hwloc_base_single_cpu(boundset)) {
 151             bound = true;
 152         }
 153     }
 154 
 155     /* If we are not bound, indicate that */
 156     if (!bound) {
 157         strncat(str, not_bound_str, OMPI_AFFINITY_STRING_MAX - 1);
 158         ret = OMPI_SUCCESS;
 159     }
 160 
 161     /* If we are bound, print it out */
 162     else {
 163         ret = opal_hwloc_base_cset2str(str, OMPI_AFFINITY_STRING_MAX,
 164                                        opal_hwloc_topology,
 165                                        boundset);
 166         if (OPAL_ERR_NOT_BOUND == ret) {
 167             opal_string_copy(str, not_bound_str, OMPI_AFFINITY_STRING_MAX);
 168             ret = OMPI_SUCCESS;
 169         }
 170     }
 171     hwloc_bitmap_free(boundset);
 172 
 173     return ret;
 174 }
 175 
 176 
 177 /*
 178  * Prettyprint a list of all available sockets and cores.  Note that
 179  * this is *everything* -- not just the ones that are available to
 180  * this process.
 181  */
 182 static int get_rsrc_exists(char str[OMPI_AFFINITY_STRING_MAX])
 183 {
 184     bool first = true;
 185     int i, num_cores, num_pus;
 186     char tmp[BUFSIZ];
 187     const int stmp = sizeof(tmp) - 1;
 188     hwloc_obj_t socket, core, c2;
 189 
 190     str[0] = '\0';
 191     for (socket = hwloc_get_obj_by_type(opal_hwloc_topology,
 192                                         HWLOC_OBJ_SOCKET, 0);
 193          NULL != socket; socket = socket->next_cousin) {
 194         /* If this isn't the first socket, add a delimiter */
 195         if (!first) {
 196             strncat(str, "; ", OMPI_AFFINITY_STRING_MAX - strlen(str));
 197         }
 198         first = false;
 199 
 200         snprintf(tmp, stmp, "socket %d has ", socket->os_index);
 201         strncat(str, tmp, OMPI_AFFINITY_STRING_MAX - strlen(str));
 202 
 203         /* Find out how many cores are inside this socket, and get an
 204            object pointing to the first core.  Also count how many PUs
 205            are in the first core. */
 206         num_cores = hwloc_get_nbobjs_inside_cpuset_by_type(opal_hwloc_topology,
 207                                                            socket->cpuset,
 208                                                            HWLOC_OBJ_CORE);
 209         core = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology,
 210                                                    socket->cpuset,
 211                                                    HWLOC_OBJ_CORE, 0);
 212         if (NULL != core) {
 213             num_pus =
 214                 hwloc_get_nbobjs_inside_cpuset_by_type(opal_hwloc_topology,
 215                                                        core->cpuset,
 216                                                        HWLOC_OBJ_PU);
 217 
 218             /* Only 1 core */
 219             if (1 == num_cores) {
 220                 strncat(str, "1 core with ",
 221                         OMPI_AFFINITY_STRING_MAX - strlen(str));
 222                 if (1 == num_pus) {
 223                     strncat(str, "1 hwt",
 224                             OMPI_AFFINITY_STRING_MAX - strlen(str));
 225                 } else {
 226                     snprintf(tmp, stmp, "%d hwts", num_pus);
 227                     strncat(str, tmp, OMPI_AFFINITY_STRING_MAX - strlen(str));
 228                 }
 229             }
 230 
 231             /* Multiple cores */
 232             else {
 233                 bool same = true;
 234 
 235                 snprintf(tmp, stmp, "%d cores", num_cores);
 236                 strncat(str, tmp, OMPI_AFFINITY_STRING_MAX - strlen(str));
 237 
 238                 /* Do all the cores have the same number of PUs? */
 239                 for (c2 = core; NULL != c2; c2 = c2->next_cousin) {
 240                     if (hwloc_get_nbobjs_inside_cpuset_by_type(opal_hwloc_topology,
 241                                                                core->cpuset,
 242                                                                HWLOC_OBJ_PU) !=
 243                         num_pus) {
 244                         same = false;
 245                         break;
 246                     }
 247                 }
 248 
 249                 /* Yes, they all have the same number of PUs */
 250                 if (same) {
 251                     snprintf(tmp, stmp, ", each with %d hwt", num_pus);
 252                     strncat(str, tmp, OMPI_AFFINITY_STRING_MAX - strlen(str));
 253                     if (num_pus != 1) {
 254                         strncat(str, "s", OMPI_AFFINITY_STRING_MAX - strlen(str));
 255                     }
 256                 }
 257 
 258                 /* No, they have differing numbers of PUs */
 259                 else {
 260                     bool first = true;
 261 
 262                     strncat(str, "with (", OMPI_AFFINITY_STRING_MAX - strlen(str));
 263                     for (c2 = core; NULL != c2; c2 = c2->next_cousin) {
 264                         if (!first) {
 265                             strncat(str, ", ",
 266                                     OMPI_AFFINITY_STRING_MAX - strlen(str));
 267                         }
 268                         first = false;
 269 
 270                         i = hwloc_get_nbobjs_inside_cpuset_by_type(opal_hwloc_topology,
 271                                                                    core->cpuset,
 272                                                                    HWLOC_OBJ_PU);
 273                         snprintf(tmp, stmp, "%d", i);
 274                         strncat(str, tmp, OMPI_AFFINITY_STRING_MAX - strlen(str));
 275                     }
 276                     strncat(str, ") hwts",
 277                             OMPI_AFFINITY_STRING_MAX - strlen(str));
 278                 }
 279             }
 280         }
 281     }
 282 
 283     return OMPI_SUCCESS;
 284 }
 285 
 286 /*---------------------------------------------------------------------------*/
 287 
 288 /*
 289  * Where did OMPI bind this process? (layout string)
 290  */
 291 static int get_layout_ompi_bound(char str[OMPI_AFFINITY_STRING_MAX])
 292 {
 293     int ret;
 294 
 295     /* If OMPI did not bind, indicate that */
 296     if (!ompi_rte_proc_is_bound) {
 297         opal_string_copy(str, ompi_nobind_str, OMPI_AFFINITY_STRING_MAX);
 298         return OMPI_SUCCESS;
 299     }
 300 
 301     /* Find out what OMPI bound us to and prettyprint it */
 302     if (NULL == ompi_proc_applied_binding) {
 303         ret = OPAL_ERR_NOT_BOUND;
 304     } else {
 305         ret = opal_hwloc_base_cset2mapstr(str, OMPI_AFFINITY_STRING_MAX,
 306                                           opal_hwloc_topology,
 307                                           ompi_proc_applied_binding);
 308     }
 309     if (OPAL_ERR_NOT_BOUND == ret) {
 310         opal_string_copy(str, not_bound_str, OMPI_AFFINITY_STRING_MAX);
 311         ret = OMPI_SUCCESS;
 312     }
 313 
 314     return ret;
 315 }
 316 
 317 /*
 318  * Where is this process currently bound? (layout string)
 319  */
 320 static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
 321 {
 322     int ret;
 323     hwloc_obj_t root;
 324     hwloc_cpuset_t boundset, rootset;
 325     bool bound = false;
 326 
 327     /* get our root object */
 328     root = hwloc_get_root_obj(opal_hwloc_topology);
 329     rootset = root->cpuset;
 330 
 331     /* get our bindings */
 332     boundset = hwloc_bitmap_alloc();
 333     if (hwloc_get_cpubind(opal_hwloc_topology, boundset,
 334                           HWLOC_CPUBIND_PROCESS) < 0) {
 335         /* we are NOT bound if get_cpubind fails, nor can we be bound
 336            - the environment does not support it */
 337         bound = false;
 338     } else {
 339         /* we are bound if the two cpusets are not equal, or if there
 340            is only ONE PU available to us */
 341         if (0 != hwloc_bitmap_compare(boundset, rootset) ||
 342             opal_hwloc_base_single_cpu(rootset) ||
 343             opal_hwloc_base_single_cpu(boundset)) {
 344             bound = true;
 345         }
 346     }
 347 
 348     /* If we are not bound, indicate that */
 349     if (!bound) {
 350         strncat(str, not_bound_str, OMPI_AFFINITY_STRING_MAX - 1);
 351         ret = OMPI_SUCCESS;
 352     }
 353 
 354     /* If we are bound, print it out */
 355     else {
 356         ret = opal_hwloc_base_cset2mapstr(str, OMPI_AFFINITY_STRING_MAX,
 357                                           opal_hwloc_topology,
 358                                           boundset);
 359         if (OPAL_ERR_NOT_BOUND == ret) {
 360             opal_string_copy(str, not_bound_str, OMPI_AFFINITY_STRING_MAX);
 361             ret = OMPI_SUCCESS;
 362         }
 363     }
 364     hwloc_bitmap_free(boundset);
 365 
 366     return ret;
 367 }
 368 
 369 /*
 370  * Make a layout string of all available sockets and cores.  Note that
 371  * this is *everything* -- not just the ones that are available to
 372  * this process.
 373  *
 374  * Example: [../..]
 375  * Key:  [] - signifies socket
 376  *        / - signifies core
 377  *        . - signifies PU
 378  */
 379 static int get_layout_exists(char str[OMPI_AFFINITY_STRING_MAX])
 380 {
 381     int core_index, pu_index;
 382     int len = OMPI_AFFINITY_STRING_MAX;
 383     hwloc_obj_t socket, core, pu;
 384 
 385     str[0] = '\0';
 386 
 387     /* Iterate over all existing sockets */
 388     for (socket = hwloc_get_obj_by_type(opal_hwloc_topology,
 389                                         HWLOC_OBJ_SOCKET, 0);
 390          NULL != socket;
 391          socket = socket->next_cousin) {
 392         strncat(str, "[", len - strlen(str));
 393 
 394         /* Iterate over all existing cores in this socket */
 395         core_index = 0;
 396         for (core = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology,
 397                                                         socket->cpuset,
 398                                                         HWLOC_OBJ_CORE, core_index);
 399              NULL != core;
 400              core = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology,
 401                                                         socket->cpuset,
 402                                                         HWLOC_OBJ_CORE, ++core_index)) {
 403             if (core_index > 0) {
 404                 strncat(str, "/", len - strlen(str));
 405             }
 406 
 407             /* Iterate over all existing PUs in this core */
 408             pu_index = 0;
 409             for (pu = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology,
 410                                                           core->cpuset,
 411                                                           HWLOC_OBJ_PU, pu_index);
 412                  NULL != pu;
 413                  pu = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology,
 414                                                           core->cpuset,
 415                                                           HWLOC_OBJ_PU, ++pu_index)) {
 416                 strncat(str, ".", len - strlen(str));
 417             }
 418         }
 419         strncat(str, "]", len - strlen(str));
 420     }
 421 
 422     return OMPI_SUCCESS;
 423 }

/* [<][>][^][v][top][bottom][index][help] */