root/ompi/mca/topo/base/topo_base_comm_select.c

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

DEFINITIONS

This source file includes following definitions.
  1. mca_topo_base_comm_select
  2. fill_null_pointers

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2013 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008-2013 Cisco Systems, Inc.  All rights reserved.
  13  * Copyright (c) 2012-2013 Inria.  All rights reserved.
  14  * $COPYRIGHT$
  15  *
  16  * Additional copyrights may follow
  17  *
  18  * $HEADER$
  19  */
  20 
  21 #include "ompi_config.h"
  22 
  23 #include <string.h>
  24 
  25 #include "opal/class/opal_list.h"
  26 #include "opal/util/argv.h"
  27 #include "opal/util/output.h"
  28 #include "ompi/mca/mca.h"
  29 #include "opal/mca/base/base.h"
  30 
  31 #include "ompi/mca/topo/topo.h"
  32 #include "ompi/mca/topo/base/base.h"
  33 #include "ompi/communicator/communicator.h"
  34 
  35 /*
  36  * Local functions
  37  */
  38 static void fill_null_pointers(int type, mca_topo_base_module_t *module);
  39 
  40 
  41 /*
  42  * This structure is needed so that we can close the modules
  43  * which are not selected but were opened. mca_base_modules_close
  44  * which does this job for us requires a opal_list_t which contains
  45  * these modules
  46  */
  47 struct queried_module_t {
  48     opal_list_item_t super;
  49     mca_topo_base_component_t *om_component;
  50     mca_topo_base_module_t *om_module;
  51 };
  52 typedef struct queried_module_t queried_module_t;
  53 static OBJ_CLASS_INSTANCE(queried_module_t, opal_list_item_t, NULL, NULL);
  54 
  55 /*
  56  * Only one topo module can be attached to each communicator. The
  57  * communicator provided as argument is the old communicator, and the
  58  * newly selected topology is __not__ supposed to be attached to it.
  59  *
  60  * This module calls the query funtion on all the components that were
  61  * detected by topo_base_open. This function is called on a
  62  * per-communicator basis. This function has the following function.
  63  *
  64  * 1. Iterate over the list of available_components.
  65  * 2. Call the query function on each of these components.
  66  * 3. The query function returns a module and its priority.
  67  * 4. Select the module with the highest priority.
  68  * 5. OBJ_RELEASE all the "losing" modules.
  69  */
  70 int mca_topo_base_comm_select(const ompi_communicator_t*  comm,
  71                               mca_topo_base_module_t*     preferred_module,
  72                               mca_topo_base_module_t**    selected_module,
  73                               uint32_t                    type)
  74 {
  75     int priority;
  76     int best_priority;
  77     opal_list_item_t *item;
  78     mca_base_component_list_item_t *cli;
  79     mca_topo_base_component_t *component;
  80     mca_topo_base_component_t *best_component;
  81     mca_topo_base_module_t *module;
  82     opal_list_t queried;
  83     queried_module_t *om;
  84     int err = MPI_SUCCESS;
  85 
  86     /* Ensure the topo framework is initialized */
  87     if (OMPI_SUCCESS != (err = mca_topo_base_lazy_init())) {
  88         return err;
  89     }
  90     opal_output_verbose(10, ompi_topo_base_framework.framework_output,
  91                         "topo:base:comm_select: new communicator: %s (cid %d)",
  92                         comm->c_name, comm->c_contextid);
  93 
  94     /* Check and see if a preferred component was provided. If it was
  95        provided then it should be used (if possible) */
  96     if (NULL != preferred_module) {
  97 
  98         /* We have a preferred module. Check if it is available
  99            and if so, whether it wants to run */
 100 
 101          opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 102                              "topo:base:comm_select: Checking preferred component: %s",
 103                              preferred_module->topo_component->topoc_version.mca_component_name);
 104 
 105          /* query the component for its priority and get its module
 106             structure. This is necessary to proceed */
 107          component = (mca_topo_base_component_t *)preferred_module->topo_component;
 108          module = component->topoc_comm_query(comm, &priority, type);
 109          if (NULL != module) {
 110 
 111              /* this query seems to have returned something legitimate
 112               * and we can now go ahead fill the NULL functions with the
 113               * corresponding base version and then return.
 114               */
 115              fill_null_pointers(type, module);
 116              *selected_module = module;
 117              module->topo_component = component;
 118              return OMPI_SUCCESS;
 119          }
 120          /* If we get here, the preferred component is present, but is
 121             unable to run.  This is not a good sign.  We should try
 122             selecting some other component.  We let it fall through
 123             and select from the list of available components */
 124     }
 125 
 126     /*
 127      * We fall here if one of the two things happened:
 128      * 1. The preferred component was provided but for some reason was
 129      *    not able to be selected
 130      * 2. No preferred component was provided
 131      *
 132      * All we need to do is to go through the list of available
 133      * components and find the one which has the highest priority and
 134      * use that for this communicator
 135      */
 136 
 137     best_component = NULL;
 138     best_priority = -1;
 139     OBJ_CONSTRUCT(&queried, opal_list_t);
 140 
 141     OPAL_LIST_FOREACH(cli, &ompi_topo_base_framework.framework_components, mca_base_component_list_item_t) {
 142        component = (mca_topo_base_component_t *) cli->cli_component;
 143        opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 144                            "select: initialising %s component %s",
 145                            component->topoc_version.mca_type_name,
 146                            component->topoc_version.mca_component_name);
 147 
 148        /*
 149         * we can call the query function only if there is a function :-)
 150         */
 151        if (NULL == component->topoc_comm_query) {
 152           opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 153                              "select: no query, ignoring the component");
 154        } else {
 155            /*
 156             * call the query function and see what it returns
 157             */
 158            module = component->topoc_comm_query(comm, &priority, type);
 159 
 160            if (NULL == module) {
 161                /*
 162                 * query did not return any action which can be used
 163                 */
 164                opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 165                                   "select: query returned failure");
 166            } else {
 167                opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 168                                   "select: query returned priority %d",
 169                                   priority);
 170                /*
 171                 * is this the best component we have found till now?
 172                 */
 173                if (priority > best_priority) {
 174                    best_priority = priority;
 175                    best_component = component;
 176                }
 177 
 178                om = OBJ_NEW(queried_module_t);
 179                /*
 180                 * check if we have run out of space
 181                 */
 182                if (NULL == om) {
 183                    OBJ_DESTRUCT(&queried);
 184                    return OMPI_ERR_OUT_OF_RESOURCE;
 185                }
 186                om->om_component = component;
 187                om->om_module = module;
 188                opal_list_append(&queried, (opal_list_item_t *)om);
 189            } /* end else of if (NULL == module) */
 190        } /* end else of if (NULL == component->init) */
 191     } /* end for ... end of traversal */
 192 
 193     /*
 194      * Now we have alist of components which successfully returned
 195      * their module struct.  One of these components has the best
 196      * priority. The rest have to be comm_unqueried to counter the
 197      * effects of comm_query'ing them. Finalize happens only on
 198      * components which should are initialized.
 199      */
 200     if (NULL == best_component) {
 201         return OMPI_ERR_NOT_FOUND;
 202     }
 203 
 204     /*
 205      * We now have a list of components which have successfully
 206      * returned their priorities from the query. We now have to
 207      * unquery() those components which have not been selected and
 208      * init() the component which was selected
 209      */
 210     for (item = opal_list_remove_first(&queried);
 211          NULL != item;
 212          item = opal_list_remove_first(&queried)) {
 213         om = (queried_module_t *) item;
 214         if (om->om_component == best_component) {
 215            /*
 216             * this is the chosen component, we have to initialise the
 217             * module of this component.
 218             *
 219             * ANJU: a component might not have all the functions
 220             * defined.  Whereever a function pointer is null in the
 221             * module structure we need to fill it in with the base
 222             * structure function pointers. This is yet to be done
 223             */
 224             fill_null_pointers(type, om->om_module);
 225             om->om_module->topo_component = best_component;
 226             *selected_module = om->om_module;
 227          } else {
 228              /* this is not the "choosen one", finalize */
 229               opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 230                                   "select: component %s is not selected",
 231                                   om->om_component->topoc_version.mca_component_name);
 232               OBJ_RELEASE(om->om_module);
 233           }
 234           OBJ_RELEASE(om);
 235     } /* traversing through the entire list */
 236 
 237     opal_output_verbose(10, ompi_topo_base_framework.framework_output,
 238                        "select: component %s selected",
 239                         best_component->topoc_version.mca_component_name);
 240     return OMPI_SUCCESS;
 241 }
 242 
 243 
 244 /*
 245  * This function fills in the null function pointers, in other words,
 246  * those functions which are not implemented by the module with the
 247  * pointers from the base function. Somewhere, I need to incoroporate
 248  * a check for the common minimum funtions being implemented by the
 249  * module.
 250  */
 251 static void fill_null_pointers(int type, mca_topo_base_module_t *module)
 252 {
 253     if( OMPI_COMM_CART == type ) {
 254         if (NULL == module->topo.cart.cart_coords) {
 255             module->topo.cart.cart_coords = mca_topo_base_cart_coords;
 256         }
 257         if (NULL == module->topo.cart.cart_create) {
 258             module->topo.cart.cart_create = mca_topo_base_cart_create;
 259         }
 260         if (NULL == module->topo.cart.cart_get) {
 261             module->topo.cart.cart_get = mca_topo_base_cart_get;
 262         }
 263         if (NULL == module->topo.cart.cartdim_get) {
 264             module->topo.cart.cartdim_get = mca_topo_base_cartdim_get;
 265         }
 266         if (NULL == module->topo.cart.cart_map) {
 267             module->topo.cart.cart_map = mca_topo_base_cart_map;
 268         }
 269         if (NULL == module->topo.cart.cart_rank) {
 270             module->topo.cart.cart_rank = mca_topo_base_cart_rank;
 271         }
 272         if (NULL == module->topo.cart.cart_shift) {
 273             module->topo.cart.cart_shift = mca_topo_base_cart_shift;
 274         }
 275         if (NULL == module->topo.cart.cart_sub) {
 276             module->topo.cart.cart_sub = mca_topo_base_cart_sub;
 277         }
 278     } else if( OMPI_COMM_GRAPH == type ) {
 279         if (NULL == module->topo.graph.graph_create) {
 280             module->topo.graph.graph_create = mca_topo_base_graph_create;
 281         }
 282         if (NULL == module->topo.graph.graph_get) {
 283             module->topo.graph.graph_get = mca_topo_base_graph_get;
 284         }
 285         if (NULL == module->topo.graph.graph_map) {
 286             module->topo.graph.graph_map = mca_topo_base_graph_map;
 287         }
 288         if (NULL == module->topo.graph.graphdims_get) {
 289             module->topo.graph.graphdims_get = mca_topo_base_graphdims_get;
 290         }
 291         if (NULL == module->topo.graph.graph_neighbors) {
 292             module->topo.graph.graph_neighbors = mca_topo_base_graph_neighbors;
 293         }
 294         if (NULL == module->topo.graph.graph_neighbors_count) {
 295             module->topo.graph.graph_neighbors_count = mca_topo_base_graph_neighbors_count;
 296         }
 297     } else if( OMPI_COMM_DIST_GRAPH == type ) {
 298         if (NULL == module->topo.dist_graph.dist_graph_create) {
 299             module->topo.dist_graph.dist_graph_create = mca_topo_base_dist_graph_create;
 300         }
 301         if (NULL == module->topo.dist_graph.dist_graph_create_adjacent) {
 302             module->topo.dist_graph.dist_graph_create_adjacent = mca_topo_base_dist_graph_create_adjacent;
 303         }
 304         if (NULL == module->topo.dist_graph.dist_graph_neighbors) {
 305             module->topo.dist_graph.dist_graph_neighbors = mca_topo_base_dist_graph_neighbors;
 306         }
 307         if (NULL == module->topo.dist_graph.dist_graph_neighbors_count) {
 308             module->topo.dist_graph.dist_graph_neighbors_count = mca_topo_base_dist_graph_neighbors_count;
 309         }
 310     }
 311 }

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