2004-07-21 02:32:45 +04:00
|
|
|
/*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ompi_config.h"
|
|
|
|
|
|
|
|
#include "class/ompi_list.h"
|
|
|
|
#include "runtime/runtime.h"
|
|
|
|
#include "mca/mca.h"
|
|
|
|
#include "mca/base/base.h"
|
|
|
|
#include "mca/topo/topo.h"
|
|
|
|
#include "mca/topo/base/base.h"
|
|
|
|
#include "util/output.h"
|
|
|
|
#include "communicator/communicator.h"
|
|
|
|
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
/*
|
|
|
|
* Local functions
|
|
|
|
*/
|
|
|
|
static void fill_null_pointers(mca_topo_base_module_t *module);
|
|
|
|
|
|
|
|
|
2004-07-21 02:32:45 +04:00
|
|
|
/*
|
|
|
|
* This structure is needed so that we can close the modules
|
|
|
|
* which are not selected but were opened. mca_base_modules_close
|
|
|
|
* which does this job for us requires a ompi_list_t which contains
|
|
|
|
* these modules
|
|
|
|
*/
|
|
|
|
struct queried_module_t {
|
|
|
|
ompi_list_item_t super;
|
2004-08-02 04:24:22 +04:00
|
|
|
mca_topo_base_component_t *om_component;
|
2004-07-21 02:32:45 +04:00
|
|
|
mca_topo_base_module_t *om_module;
|
|
|
|
};
|
|
|
|
typedef struct queried_module_t queried_module_t;
|
|
|
|
OBJ_CLASS_INSTANCE(queried_module_t, ompi_list_item_t, NULL, NULL);
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
|
2004-07-21 02:32:45 +04:00
|
|
|
/*
|
|
|
|
* Only one topo module can be attached to each communicator.
|
|
|
|
*
|
2004-08-02 04:24:22 +04:00
|
|
|
* This module calls the query funtion on all the components that were
|
|
|
|
* detected by topo_base_open. This function is called on a
|
|
|
|
* per-communicator basis. This function has the following function.
|
2004-07-21 02:32:45 +04:00
|
|
|
*
|
2004-08-02 04:24:22 +04:00
|
|
|
* 1. Iterate over the list of available_components
|
|
|
|
* 2. Call the query function on each of these components.
|
2004-07-21 02:32:45 +04:00
|
|
|
* 3. query function returns the structure containing pointers
|
2004-08-02 04:24:22 +04:00
|
|
|
* to its module and its priority
|
2004-07-21 02:32:45 +04:00
|
|
|
* 4. Select the module with the highest priority
|
2004-08-02 04:24:22 +04:00
|
|
|
* 5. Call the init function on the selected module so that it does the
|
2004-07-21 02:32:45 +04:00
|
|
|
* right setup for the communicator
|
|
|
|
* 6. Call finalize on all the other modules which returned
|
2004-08-02 04:24:22 +04:00
|
|
|
* their module but were unfortunate to not get selected
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
int mca_topo_base_comm_select (struct ompi_communicator_t *comm,
|
2004-08-02 04:24:22 +04:00
|
|
|
struct mca_base_component_t *preferred)
|
|
|
|
{
|
2004-07-21 02:32:45 +04:00
|
|
|
int priority;
|
|
|
|
int best_priority;
|
|
|
|
char name[MPI_MAX_OBJECT_NAME+32];
|
|
|
|
ompi_list_item_t *item;
|
|
|
|
mca_base_component_priority_list_item_t *cpli;
|
2004-08-02 04:24:22 +04:00
|
|
|
mca_topo_base_component_t *component;
|
|
|
|
mca_topo_base_component_t *preferred_component = NULL;
|
|
|
|
mca_topo_base_component_t *best_component;
|
2004-07-21 02:32:45 +04:00
|
|
|
mca_topo_base_module_t *module;
|
|
|
|
ompi_list_t queried;
|
|
|
|
queried_module_t *om;
|
|
|
|
char *str;
|
|
|
|
int err;
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
/* Announce */
|
2004-07-21 02:32:45 +04:00
|
|
|
|
|
|
|
/* ANJU:
|
|
|
|
* check for names array .... mca_base_param_ */
|
|
|
|
|
|
|
|
snprintf(name, sizeof(name), "%s (cid %d)", comm->c_name,
|
|
|
|
comm->c_contextid);
|
|
|
|
name[sizeof(name) - 1] = '\0';
|
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
|
|
|
"topo:base:comm_select: new communicator: %s",
|
|
|
|
name);
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
/* Check and see if a preferred component was provided. If it was
|
|
|
|
provided then it should be used (if possible) */
|
|
|
|
|
2004-07-21 02:32:45 +04:00
|
|
|
if (NULL != preferred) {
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
/* We have a preferred component. Check if it is available
|
2004-07-21 02:32:45 +04:00
|
|
|
and if so, whether it wants to run */
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
str = &(preferred->mca_component_name[0]);
|
2004-07-21 02:32:45 +04:00
|
|
|
|
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
2004-08-02 04:24:22 +04:00
|
|
|
"topo:base:comm_select: Checking preferred component: %s",
|
2004-07-21 02:32:45 +04:00
|
|
|
str);
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
/* query the component for its priority and get its module
|
2004-07-21 02:32:45 +04:00
|
|
|
structure. This is necessary to proceed */
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
module = preferred_component->topom_comm_query (&priority);
|
|
|
|
if (NULL != module &&
|
|
|
|
NULL != module->topo_module_init &&
|
|
|
|
NULL != module->topo_graph_map &&
|
|
|
|
NULL != module->topo_cart_map) {
|
2004-07-21 02:32:45 +04:00
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
/* this query seems to have returned something legitimate
|
|
|
|
* and we can now go ahead and initialize the
|
|
|
|
* communicator with it * but first, the functions which
|
|
|
|
* are null need to be filled in */
|
2004-07-21 02:32:45 +04:00
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
fill_null_pointers (module);
|
|
|
|
comm->c_topo = module;
|
|
|
|
return module->topo_module_init(comm);
|
2004-07-21 02:32:45 +04:00
|
|
|
}
|
2004-08-02 04:24:22 +04:00
|
|
|
/* His preferred component is present, but is unable to
|
|
|
|
* run. This is not a good sign. We should try selecting
|
|
|
|
* some other component We let it fall through and select
|
|
|
|
* from the list of available components
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
} /*end of selection for preferred component */
|
2004-07-21 02:32:45 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We fall till here if one of the two things happened:
|
2004-08-02 04:24:22 +04:00
|
|
|
* 1. The preferred component was provided but for some reason was
|
|
|
|
* not able to be selected
|
|
|
|
* 2. No preferred component was provided
|
2004-07-21 02:32:45 +04:00
|
|
|
*
|
2004-08-02 04:24:22 +04:00
|
|
|
* All we need to do is to go through the list of available
|
|
|
|
* components and find the one which has the highest priority and
|
|
|
|
* use that for this communicator
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
best_component = NULL;
|
2004-07-21 02:32:45 +04:00
|
|
|
best_priority = -1;
|
|
|
|
OBJ_CONSTRUCT(&queried, ompi_list_t);
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
for (item = ompi_list_get_first(&mca_topo_base_components_available);
|
|
|
|
item != ompi_list_get_end(&mca_topo_base_components_available);
|
2004-07-21 02:32:45 +04:00
|
|
|
item = ompi_list_get_next(item)) {
|
|
|
|
/*
|
|
|
|
* convert the ompi_list_item_t returned into the proper type
|
|
|
|
*/
|
|
|
|
cpli = (mca_base_component_priority_list_item_t *) item;
|
2004-08-02 04:24:22 +04:00
|
|
|
component = (mca_topo_base_component_t *) cpli->cpli_component;
|
2004-07-21 02:32:45 +04:00
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
2004-08-02 04:24:22 +04:00
|
|
|
"select: initialising %s component %s",
|
|
|
|
component->topom_version.mca_type_name,
|
|
|
|
component->topom_version.mca_component_name);
|
2004-07-21 02:32:45 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* we can call the query function only if there is a function :-)
|
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
if (NULL == component->topom_comm_query) {
|
2004-07-21 02:32:45 +04:00
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
2004-08-02 04:24:22 +04:00
|
|
|
"select: no query, ignoring the component");
|
2004-07-21 02:32:45 +04:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* call the query function and see what it returns
|
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
module = component->topom_comm_query (&priority);
|
2004-07-21 02:32:45 +04:00
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
if (NULL == module ||
|
|
|
|
NULL == module->topo_module_init ||
|
|
|
|
NULL == module->topo_graph_map ||
|
|
|
|
NULL == module->topo_cart_map) {
|
2004-07-21 02:32:45 +04:00
|
|
|
/*
|
|
|
|
* query did not return any action which can be used
|
|
|
|
*/
|
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
|
|
|
"select: query returned failure");
|
|
|
|
} else {
|
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
|
|
|
"select: query returned priority &d",
|
|
|
|
priority);
|
|
|
|
/*
|
2004-08-02 04:24:22 +04:00
|
|
|
* is this the best component we have found till now?
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
|
|
|
if (priority > best_priority) {
|
|
|
|
best_priority = priority;
|
2004-08-02 04:24:22 +04:00
|
|
|
best_component = component;
|
2004-07-21 02:32:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
om = OBJ_NEW(queried_module_t);
|
|
|
|
/*
|
|
|
|
* check if we have run out of space
|
|
|
|
*/
|
|
|
|
if (NULL == om) {
|
|
|
|
OBJ_DESTRUCT(&queried);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
2004-08-02 04:24:22 +04:00
|
|
|
om->om_component = component;
|
|
|
|
om->om_module = module;
|
2004-07-21 02:32:45 +04:00
|
|
|
ompi_list_append(&queried, (ompi_list_item_t *)om);
|
2004-08-02 04:24:22 +04:00
|
|
|
} /* end else of if (NULL == module) */
|
|
|
|
} /* end else of if (NULL == component->topom_init) */
|
2004-07-21 02:32:45 +04:00
|
|
|
} /* end for ... end of traversal */
|
|
|
|
|
|
|
|
/*
|
2004-08-02 04:24:22 +04:00
|
|
|
* Now we have alist of components which successfully returned
|
|
|
|
* their module struct. One of these components has the best
|
|
|
|
* priority. The rest have to be comm_unqueried to counter the
|
|
|
|
* effects of comm_query'ing them. Finalize happens only on
|
|
|
|
* components which should are initialized.
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
if (NULL == best_component) {
|
2004-07-21 02:32:45 +04:00
|
|
|
/*
|
2004-08-02 04:24:22 +04:00
|
|
|
* This typically means that there was no component which was
|
|
|
|
* able to run properly this time. So, we need to abort
|
2004-07-21 02:32:45 +04:00
|
|
|
* JMS replace with show_help
|
|
|
|
*/
|
|
|
|
OBJ_DESTRUCT(&queried);
|
|
|
|
return OMPI_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-08-02 04:24:22 +04:00
|
|
|
* We now have a list of components which have successfully
|
|
|
|
* returned their priorities from the query. We now have to
|
|
|
|
* unquery() those components which have not been selected and
|
|
|
|
* init() the component which was selected
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
|
|
|
for (item = ompi_list_remove_first(&queried);
|
|
|
|
NULL != item;
|
|
|
|
item = ompi_list_remove_first(&queried)) {
|
|
|
|
om = (queried_module_t *) item;
|
2004-08-02 04:24:22 +04:00
|
|
|
if (om->om_component == best_component) {
|
2004-07-21 02:32:45 +04:00
|
|
|
/*
|
2004-08-02 04:24:22 +04:00
|
|
|
* this is the chosen component, we have to initialise the
|
|
|
|
* module of this component.
|
2004-07-21 02:32:45 +04:00
|
|
|
*
|
2004-08-02 04:24:22 +04:00
|
|
|
* ANJU: a component might not have all the functions
|
|
|
|
* defined. Whereever a function pointer is null in the
|
|
|
|
* module structure we need to fill it in with the base
|
|
|
|
* structure function pointers. This is yet to be done
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2004-08-02 04:24:22 +04:00
|
|
|
* We don return here coz we still need to go through and
|
|
|
|
* elease the other objects
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
fill_null_pointers (om->om_module);
|
|
|
|
comm->c_topo = om->om_module;
|
|
|
|
err = module->topo_module_init(comm);
|
2004-07-21 02:32:45 +04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* this is not the "choosen one", finalize
|
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
if (NULL != om->om_component->topom_comm_unquery) {
|
|
|
|
/* unquery the component only if they have some clean
|
|
|
|
* up job to do. Components which are queried but do
|
|
|
|
* not actually do anything typically do not have a
|
|
|
|
* unquery. Hence this check is necessary
|
2004-07-21 02:32:45 +04:00
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
(void) om->om_component->topom_comm_unquery(comm);
|
2004-07-21 02:32:45 +04:00
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
2004-08-02 04:24:22 +04:00
|
|
|
"select: component %s is not selected",
|
|
|
|
om->om_component->topom_version.mca_component_name);
|
2004-07-21 02:32:45 +04:00
|
|
|
} /* end if */
|
2004-08-02 04:24:22 +04:00
|
|
|
} /* if not best component */
|
2004-07-21 02:32:45 +04:00
|
|
|
OBJ_RELEASE(om);
|
|
|
|
} /* traversing through the entire list */
|
|
|
|
|
|
|
|
ompi_output_verbose(10, mca_topo_base_output,
|
2004-08-02 04:24:22 +04:00
|
|
|
"select: component %s selected",
|
|
|
|
component->topom_version.mca_component_name);
|
2004-07-21 02:32:45 +04:00
|
|
|
|
|
|
|
OBJ_DESTRUCT(&queried);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2004-08-02 04:24:22 +04:00
|
|
|
|
2004-07-21 02:32:45 +04:00
|
|
|
/*
|
|
|
|
* This function fills in the null function pointers, in other words,
|
2004-08-02 04:24:22 +04:00
|
|
|
* those functions which are not implemented by the module with the
|
|
|
|
* pointers from the base function. Somewhere, I need to incoroporate
|
|
|
|
* a check for the common minimum funtions being implemented by the
|
2004-07-21 02:32:45 +04:00
|
|
|
* module atleast. If not, this module cannot be considered.
|
|
|
|
*/
|
2004-08-02 04:24:22 +04:00
|
|
|
static void fill_null_pointers(mca_topo_base_module_t *module)
|
|
|
|
{
|
2004-07-21 02:32:45 +04:00
|
|
|
#define CHECK_FOR_NULL_FUNCTION_POINTER(name) \
|
2004-08-02 04:24:22 +04:00
|
|
|
if (NULL == module->topo_##name) { \
|
|
|
|
module->topo_##name = mca_topo_base_##name; \
|
2004-07-21 02:32:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(cart_coords);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(cart_create);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(cartdim_get);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(cart_rank);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(cart_shift);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(cart_sub);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(graph_create);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(graph_get);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(graphdims_get);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(graph_neighbors);
|
|
|
|
CHECK_FOR_NULL_FUNCTION_POINTER(graph_neighbors_count);
|
|
|
|
|
|
|
|
#undef CHECK_FOR_NULL_FUNCTION_POINTER
|
|
|
|
}
|