[mpich-commits] [mpich] MPICH primary repository branch, master, updated. v3.2-372-g679bd67

Service Account noreply at mpich.org
Wed Jul 27 14:57:59 CDT 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "MPICH primary repository".

The branch, master has been updated
       via  679bd676e9dbdc8926f20ecc9f4bd45d1d41f4f6 (commit)
       via  355a3e01c52f914d235a6a387dd0e13a6fcc6f8f (commit)
      from  0d6412303488428c461986655a56639cbbdbf705 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.mpich.org/mpich.git/commitdiff/679bd676e9dbdc8926f20ecc9f4bd45d1d41f4f6

commit 679bd676e9dbdc8926f20ecc9f4bd45d1d41f4f6
Author: Yanfei Guo <yguo at anl.gov>
Date:   Thu Apr 21 22:00:28 2016 -0500

    util: Put nodemap code in util layer
    
    Hoist generic nodemap code out of CH3 and into the util layer for use
    by other devices.
    
    Signed-off-by: Ken Raffenetti <raffenet at mcs.anl.gov>

diff --git a/src/mpid/ch3/src/mpid_vc.c b/src/mpid/ch3/src/mpid_vc.c
index aa70c6a..02417bc 100644
--- a/src/mpid/ch3/src/mpid_vc.c
+++ b/src/mpid/ch3/src/mpid_vc.c
@@ -22,36 +22,11 @@
 #endif
 #include <ctype.h>
 
+#include "build_nodemap.h"
 /*
 === BEGIN_MPI_T_CVAR_INFO_BLOCK ===
 
 cvars:
-    - name        : MPIR_CVAR_CH3_NOLOCAL
-      category    : CH3
-      alt-env     : MPIR_CVAR_CH3_NO_LOCAL
-      type        : boolean
-      default     : false
-      class       : none
-      verbosity   : MPI_T_VERBOSITY_USER_BASIC
-      scope       : MPI_T_SCOPE_ALL_EQ
-      description : >-
-        If true, force all processes to operate as though all processes
-        are located on another node.  For example, this disables shared
-        memory communication hierarchical collectives.
-
-    - name        : MPIR_CVAR_CH3_ODD_EVEN_CLIQUES
-      category    : CH3
-      alt-env     : MPIR_CVAR_CH3_EVEN_ODD_CLIQUES
-      type        : boolean
-      default     : false
-      class       : none
-      verbosity   : MPI_T_VERBOSITY_USER_BASIC
-      scope       : MPI_T_SCOPE_ALL_EQ
-      description : >-
-        If true, odd procs on a node are seen as local to each other, and even
-        procs on a node are seen as local to each other.  Used for debugging on
-        a single machine.
-
     - name        : MPIR_CVAR_CH3_EAGER_MAX_MSG_SIZE
       category    : CH3
       type        : int
@@ -683,333 +658,6 @@ int MPID_Get_max_node_id(MPIR_Comm *comm, MPID_Node_id_t *max_id_p)
     return MPI_SUCCESS;
 }
 
-#if !defined(USE_PMI2_API)
-/* this function is not used in pmi2 */
-static int publish_node_id(MPIDI_PG_t *pg, int our_pg_rank)
-{
-    int mpi_errno = MPI_SUCCESS;
-    int pmi_errno;
-    int ret;
-    char *key;
-    int key_max_sz;
-    char *kvs_name;
-    MPIR_CHKLMEM_DECL(1);
-
-    /* set MPIU_hostname */
-    ret = gethostname(MPIU_hostname, MAX_HOSTNAME_LEN);
-    MPIR_ERR_CHKANDJUMP2(ret == -1, mpi_errno, MPI_ERR_OTHER, "**sock_gethost", "**sock_gethost %s %d", MPIR_Strerror(errno), errno);
-    MPIU_hostname[MAX_HOSTNAME_LEN-1] = '\0';
-
-    /* Allocate space for pmi key */
-    pmi_errno = PMI_KVS_Get_key_length_max(&key_max_sz);
-    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
-
-    MPIR_CHKLMEM_MALLOC(key, char *, key_max_sz, mpi_errno, "key");
-
-    mpi_errno = MPIDI_PG_GetConnKVSname(&kvs_name);
-    if (mpi_errno) MPIR_ERR_POP(mpi_errno);
-
-    /* Put my hostname id */
-    if (pg->size > 1)
-    {
-        memset(key, 0, key_max_sz);
-        MPL_snprintf(key, key_max_sz, "hostname[%d]", our_pg_rank);
-
-        pmi_errno = PMI_KVS_Put(kvs_name, key, MPIU_hostname);
-        MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_kvs_put", "**pmi_kvs_put %d", pmi_errno);
-
-        pmi_errno = PMI_KVS_Commit(kvs_name);
-        MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_kvs_commit", "**pmi_kvs_commit %d", pmi_errno);
-
-        pmi_errno = PMI_Barrier();
-        MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_barrier", "**pmi_barrier %d", pmi_errno);
-    }
-    
-fn_exit:
-    MPIR_CHKLMEM_FREEALL();
-    return mpi_errno;
-fn_fail:
-    goto fn_exit;
-}
-#endif
-
-
-#define parse_error() MPIR_ERR_INTERNALANDJUMP(mpi_errno, "parse error")
-/* advance _c until we find a non whitespace character */
-#define skip_space(_c) while (isspace(*(_c))) ++(_c)
-/* return true iff _c points to a character valid as an indentifier, i.e., [-_a-zA-Z0-9] */
-#define isident(_c) (isalnum(_c) || (_c) == '-' || (_c) == '_')
-
-/* give an error iff *_c != _e */
-#define expect_c(_c, _e) do { if (*(_c) != _e) parse_error(); } while (0)
-#define expect_and_skip_c(_c, _e) do { expect_c(_c, _e); ++c; } while (0)
-/* give an error iff the first |_m| characters of the string _s are equal to _e */
-#define expect_s(_s, _e) (strncmp(_s, _e, strlen(_e)) == 0 && !isident((_s)[strlen(_e)]))
-
-typedef enum {
-    UNKNOWN_MAPPING = -1,
-    NULL_MAPPING = 0,
-    VECTOR_MAPPING
-} mapping_type_t;
-
-#define VECTOR "vector"
-
-typedef struct map_block
-{
-    int start_id;
-    int count;
-    int size;
-} map_block_t;
-
-#undef FUNCNAME
-#define FUNCNAME parse_mapping
-#undef FCNAME
-#define FCNAME MPL_QUOTE(FUNCNAME)
-static int parse_mapping(char *map_str, mapping_type_t *type, map_block_t **map, int *nblocks)
-{
-    int mpi_errno = MPI_SUCCESS;
-    char *c = map_str, *d;
-    int num_blocks = 0;
-    int i;
-    MPIR_CHKPMEM_DECL(1);
-    MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_PARSE_MAPPING);
-
-    MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_PARSE_MAPPING);
-
-    /* parse string of the form:
-       '(' <format> ',' '(' <num> ',' <num> ',' <num> ')' {',' '(' <num> ',' <num> ',' <num> ')'} ')'
-
-       the values of each 3-tuple have the following meaning (X,Y,Z):
-         X - node id start value
-         Y - number of nodes with size Z
-         Z - number of processes assigned to each node
-     */
-    MPL_DBG_MSG_S(MPIDI_CH3_DBG_OTHER,VERBOSE,"parsing mapping string '%s'", map_str);
-
-    if (!strlen(map_str)) {
-        /* An empty-string indicates an inability to determine or express the
-         * process layout on the part of the process manager.  Consider this a
-         * non-fatal error case. */
-        *type = NULL_MAPPING;
-        *map = NULL;
-        *nblocks = 0;
-        goto fn_exit;
-    }
-
-    skip_space(c);
-    expect_and_skip_c(c, '(');
-    skip_space(c);
-
-    d = c;
-    if (expect_s(d, VECTOR))
-        *type = VECTOR_MAPPING;
-    else
-        parse_error();
-    c += strlen(VECTOR);
-    skip_space(c);
-
-    /* first count the number of block descriptors */
-    d = c;
-    while (*d) {
-        if (*d == '(')
-            ++num_blocks;
-        ++d;
-    }
-
-    MPIR_CHKPMEM_MALLOC(*map, map_block_t *, sizeof(map_block_t) * num_blocks, mpi_errno, "map");
-
-    /* parse block descriptors */
-    for (i = 0; i < num_blocks; ++i) {
-        expect_and_skip_c(c, ',');
-        skip_space(c);
-
-        expect_and_skip_c(c, '(');
-        skip_space(c);
-
-        if (!isdigit(*c))
-            parse_error();
-        (*map)[i].start_id = (int)strtol(c, &c, 0);
-        skip_space(c);
-
-        expect_and_skip_c(c, ',');
-        skip_space(c);
-
-        if (!isdigit(*c))
-            parse_error();
-        (*map)[i].count = (int)strtol(c, &c, 0);
-        skip_space(c);
-
-        expect_and_skip_c(c, ',');
-        skip_space(c);
-
-        if (!isdigit(*c))
-            parse_error();
-        (*map)[i].size = (int)strtol(c, &c, 0);
-
-        expect_and_skip_c(c, ')');
-        skip_space(c);
-    }
-
-    expect_and_skip_c(c, ')');
-
-    *nblocks = num_blocks;
-    MPIR_CHKPMEM_COMMIT();
-fn_exit:
-    MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_PARSE_MAPPING);
-    return mpi_errno;
-fn_fail:
-    /* --BEGIN ERROR HANDLING-- */
-    MPIR_CHKPMEM_REAP();
-    goto fn_exit;
-    /* --END ERROR HANDLING-- */
-}
-
-#if 0
-static void t(const char *s, int nprocs)
-{
-    int ret;
-    map_block_t *mb;
-    int nblocks=0;
-    int i;
-    mapping_type_t mt = UNKNOWN_MAPPING;
-    int rank;
-    int block, block_node, node_proc;
-
-    ret = parse_mapping(strdup(s), &mt, &mb, &nblocks);
-    printf("str=\"%s\" type=%d ret=%d\n", s, mt, ret);
-    if (ret) return;
-    for (i = 0; i < nblocks; ++i)
-        printf("    %d: start=%d size=%d count=%d\n", i, mb[i].start_id, mb[i].size, mb[i].count);
-    printf("\n");
-
-
-    rank = 0;
-    while (rank < nprocs) {
-        int node_id;
-        for (block = 0; block < nblocks; ++block) {
-            node_id = mb[block].start_id;
-            for (block_node = 0; block_node < mb[block].count; ++block_node) {
-                for (node_proc = 0; node_proc < mb[block].size; ++node_proc) {
-                    printf("    %d  %d\n", rank, node_id);
-                    ++rank;
-                    if (rank == nprocs)
-                        goto done;
-                }
-                ++node_id;
-            }
-        }
-    }
-done:
-    return;
-
-}
-
-
- void test_parse_mapping(void)
-{
-    t("(vector, (0,1,1))", 5);
-    t("(vector, (0,1,1), (1,5,3), (6,2, 5))", 100);
-    t("(vector, (1,1,1), (0,2,2))", 5);
-    
-    t("(vector, (1,1,1), (0,2,2),)", 5);
-    t("XXX, (1,1))", 1);
-    t("vector, (1,1))", 1);
-    t("(vector, (1.11, 2,2))", 1);
-    t("", 1);
-
-}
-
-
-#endif
-
-#undef FUNCNAME
-#define FUNCNAME populate_ids_from_mapping
-#undef FCNAME
-#define FCNAME MPL_QUOTE(FUNCNAME)
-static int populate_ids_from_mapping(char *mapping, MPID_Node_id_t *max_node_id, MPIDI_PG_t *pg, int *did_map)
-{
-    int mpi_errno = MPI_SUCCESS;
-    /* PMI_process_mapping is available */
-    mapping_type_t mt = UNKNOWN_MAPPING;
-    map_block_t *mb = NULL;
-    int nblocks = 0;
-    int rank;
-    int block, block_node, node_proc;
-    int i;
-    int found_wrap;
-
-    *did_map = 1; /* reset upon failure */
-
-    mpi_errno = parse_mapping(mapping, &mt, &mb, &nblocks);
-    if (mpi_errno) MPIR_ERR_POP(mpi_errno);
-
-    if (NULL_MAPPING == mt) goto fn_fail;
-    MPIR_ERR_CHKINTERNAL(mt != VECTOR_MAPPING, mpi_errno, "unsupported mapping type");
-
-    /* allocate nodes to ranks */
-    found_wrap = 0;
-    for (rank = 0;;) {
-        /* FIXME: The patch is hacky because it assumes that seeing a
-         * start node ID of 0 means a wrap around.  This is not
-         * necessarily true.  A user-defined node list can, in theory,
-         * use the node ID 0 without actually creating a wrap around.
-         * The reason this patch still works in this case is because
-         * Hydra creates a new node list starting from node ID 0 for
-         * user-specified nodes during MPI_Comm_spawn{_multiple}.  If
-         * a different process manager searches for allocated nodes in
-         * the user-specified list, this patch will break. */
-
-        /* If we found that the blocks wrap around, repeat loops
-         * should only start at node id 0 */
-        for (block = 0; found_wrap && mb[block].start_id; block++);
-
-        for (; block < nblocks; block++) {
-            if (mb[block].start_id == 0)
-                found_wrap = 1;
-            for (block_node = 0; block_node < mb[block].count; block_node++) {
-                for (node_proc = 0; node_proc < mb[block].size; node_proc++) {
-                    pg->vct[rank].node_id = mb[block].start_id + block_node;
-                    if (++rank == pg->size)
-                        goto break_out;
-                }
-            }
-        }
-    }
-
- break_out:
-    /* identify maximum node id */
-    *max_node_id = -1;
-    for (i = 0; i < pg->size; i++)
-        if (pg->vct[i].node_id + 1 > *max_node_id)
-            *max_node_id = pg->vct[i].node_id;
-
-fn_exit:
-    MPL_free(mb);
-    return mpi_errno;
-fn_fail:
-    /* --BEGIN ERROR HANDLING-- */
-    *did_map = 0;
-    goto fn_exit;
-    /* --END ERROR HANDLING-- */
-}
-
-/* Fills in the node_id info from PMI info.  Adapted from MPIU_Get_local_procs.
-   This function is collective over the entire PG because PMI_Barrier is called.
-
-   our_pg_rank should be set to -1 if this is not the current process' PG.  This
-   is currently not supported due to PMI limitations.
-
-   Fallback Algorithm:
-
-   Each process kvs_puts its hostname and stores the total number of
-   processes (g_num_global).  Each process determines maximum node id
-   (g_max_node_id) and assigns a node id to each process (g_node_ids[]):
-
-     For each hostname the process seaches the list of unique nodes
-     names (node_names[]) for a match.  If a match is found, the node id
-     is recorded for that matching process.  Otherwise, the hostname is
-     added to the list of node names.
-*/
 #undef FUNCNAME
 #define FUNCNAME MPIDI_Populate_vc_node_ids
 #undef FCNAME
@@ -1017,178 +665,20 @@ fn_fail:
 int MPIDI_Populate_vc_node_ids(MPIDI_PG_t *pg, int our_pg_rank)
 {
     int mpi_errno = MPI_SUCCESS;
-    int pmi_errno;
-    int i, j;
-    char *key;
-    char *value;
-    int key_max_sz;
-    int val_max_sz;
-    char *kvs_name;
-    char **node_names;
-    char *node_name_buf;
-    int no_local = 0;
-    int odd_even_cliques = 0;
-    int pmi_version = MPIDI_CH3I_DEFAULT_PMI_VERSION;
-    int pmi_subversion = MPIDI_CH3I_DEFAULT_PMI_SUBVERSION;
-    MPIR_CHKLMEM_DECL(4);
-
-    /* See if the user wants to override our default values */
-    MPL_env2int("PMI_VERSION", &pmi_version);
-    MPL_env2int("PMI_SUBVERSION", &pmi_subversion);
-
-    if (pg->size == 1) {
-        pg->vct[0].node_id = ++g_max_node_id;
-        goto fn_exit;
-    }
-
-    /* Used for debugging only.  This disables communication over shared memory */
-#ifdef ENABLED_NO_LOCAL
-    no_local = 1;
-#else
-    no_local = MPIR_CVAR_CH3_NOLOCAL;
-#endif
-
-    /* Used for debugging on a single machine: Odd procs on a node are
-       seen as local to each other, and even procs on a node are seen
-       as local to each other. */
-#ifdef ENABLED_ODD_EVEN_CLIQUES
-    odd_even_cliques = 1;
-#else
-    odd_even_cliques = MPIR_CVAR_CH3_ODD_EVEN_CLIQUES;
-#endif
-
-    if (no_local) {
-        /* just assign 0 to n-1 as node ids and bail */
-        for (i = 0; i < pg->size; ++i) {
-            pg->vct[i].node_id = ++g_max_node_id;
-        }
-        goto fn_exit;
-    }
-
-#ifdef USE_PMI2_API
-    {
-        char process_mapping[PMI2_MAX_VALLEN];
-        int outlen;
-        int found = FALSE;
-        int i;
-        map_block_t *mb;
-        int nblocks;
-        int rank;
-        int block, block_node, node_proc;
-        int did_map = 0;
-
-        mpi_errno = PMI2_Info_GetJobAttr("PMI_process_mapping", process_mapping, sizeof(process_mapping), &found);
-        if (mpi_errno) MPIR_ERR_POP(mpi_errno);
-        MPIR_ERR_CHKINTERNAL(!found, mpi_errno, "PMI_process_mapping attribute not found");
-        /* this code currently assumes pg is comm_world */
-        mpi_errno = populate_ids_from_mapping(process_mapping, &g_max_node_id, pg, &did_map);
-        if (mpi_errno) MPIR_ERR_POP(mpi_errno);
-        MPIR_ERR_CHKINTERNAL(!did_map, mpi_errno, "unable to populate node ids from PMI_process_mapping");
-    }
-#else /* USE_PMI2_API */
-    if (our_pg_rank == -1) {
-        /* FIXME this routine can't handle the dynamic process case at this
-           time.  This will require more support from the process manager. */
-        MPIR_Assert(0);
-    }
-
-    /* Allocate space for pmi key and value */
-    pmi_errno = PMI_KVS_Get_key_length_max(&key_max_sz);
-    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
-    MPIR_CHKLMEM_MALLOC(key, char *, key_max_sz, mpi_errno, "key");
-
-    pmi_errno = PMI_KVS_Get_value_length_max(&val_max_sz);
-    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
-    MPIR_CHKLMEM_MALLOC(value, char *, val_max_sz, mpi_errno, "value");
-
-    mpi_errno = MPIDI_PG_GetConnKVSname(&kvs_name);
-    if (mpi_errno) MPIR_ERR_POP(mpi_errno);
-
-    /* See if process manager supports PMI_process_mapping keyval */
-
-    if (pmi_version == 1 && pmi_subversion == 1) {
-        pmi_errno = PMI_KVS_Get(kvs_name, "PMI_process_mapping", value, val_max_sz);
-        if (pmi_errno == 0) {
-            int did_map = 0;
-            /* this code currently assumes pg is comm_world */
-            mpi_errno = populate_ids_from_mapping(value, &g_max_node_id, pg, &did_map);
-            if (mpi_errno) MPIR_ERR_POP(mpi_errno);
-            if (did_map) {
-                goto odd_even_cliques;
-            }
-            else {
-                MPL_DBG_MSG_S(MPIDI_CH3_DBG_OTHER,TERSE,"did_map==0, unable to populate node ids from mapping=%s",value);
-            }
-            /* else fall through to O(N^2) PMI_KVS_Gets version */
-        }
-        else {
-            MPL_DBG_MSG(MPIDI_CH3_DBG_OTHER,TERSE,"unable to obtain the 'PMI_process_mapping' PMI key");
-        }
-    }
+    int i;
+    MPID_Node_id_t *out_nodemap;
+    out_nodemap = (MPID_Node_id_t *) MPL_malloc(pg->size * sizeof(MPID_Node_id_t));
 
-    mpi_errno = publish_node_id(pg, our_pg_rank);
+    mpi_errno = MPIR_NODEMAP_build_nodemap(pg->size, our_pg_rank, out_nodemap, &g_max_node_id);
     if (mpi_errno) MPIR_ERR_POP(mpi_errno);
+    MPIR_Assert(g_max_node_id >= 0);
 
-    /* Allocate temporary structures.  These would need to be persistent if
-       we somehow were able to support dynamic processes via this method. */
-    MPIR_CHKLMEM_MALLOC(node_names, char **, pg->size * sizeof(char*), mpi_errno, "node_names");
-    MPIR_CHKLMEM_MALLOC(node_name_buf, char *, pg->size * key_max_sz * sizeof(char), mpi_errno, "node_name_buf");
-
-    /* Gather hostnames */
-    for (i = 0; i < pg->size; ++i)
-    {
-        node_names[i] = &node_name_buf[i * key_max_sz];
-        node_names[i][0] = '\0';
-    }
-
-    g_max_node_id = -1; /* defensive */
-
-    for (i = 0; i < pg->size; ++i)
-    {
-        MPIR_Assert(g_max_node_id < pg->size);
-        if (i == our_pg_rank)
-        {
-            /* This is us, no need to perform a get */
-            MPL_snprintf(node_names[g_max_node_id+1], key_max_sz, "%s", MPIU_hostname);
-        }
-        else
-        {
-            memset(key, 0, key_max_sz);
-            MPL_snprintf(key, key_max_sz, "hostname[%d]", i);
-
-            pmi_errno = PMI_KVS_Get(kvs_name, key, node_names[g_max_node_id+1], key_max_sz);
-            MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_kvs_get", "**pmi_kvs_get %d", pmi_errno);
-        }
-
-        /* Find the node_id for this process, or create a new one */
-        /* FIXME:need a better algorithm -- this one does O(N^2) strncmp()s! */
-        /* The right fix is to get all this information from the process
-           manager, rather than bother with this hostname hack at all. */
-        for (j = 0; j < g_max_node_id + 1; ++j)
-            if (!strncmp(node_names[j], node_names[g_max_node_id+1], key_max_sz))
-                break;
-        if (j == g_max_node_id + 1)
-            ++g_max_node_id;
-        else
-            node_names[g_max_node_id+1][0] = '\0';
-        pg->vct[i].node_id = j;
+    for (i = 0; i < pg->size; i++) {
+        pg->vct[i].node_id = out_nodemap[i];
     }
 
-odd_even_cliques:
-    if (odd_even_cliques)
-    {
-        /* Create new processes for all odd numbered processes. This
-           may leave nodes ids with no processes assigned to them, but
-           I think this is OK */
-        for (i = 0; i < pg->size; ++i)
-            if (i & 0x1)
-                pg->vct[i].node_id += g_max_node_id + 1;
-        g_max_node_id = (g_max_node_id + 1) * 2;
-    }
-#endif
-
 fn_exit:
-    MPIR_CHKLMEM_FREEALL();
+    MPL_free(out_nodemap);
     return mpi_errno;
 fn_fail:
     goto fn_exit;
diff --git a/src/util/Makefile.mk b/src/util/Makefile.mk
index f97cc63..b98fc67 100644
--- a/src/util/Makefile.mk
+++ b/src/util/Makefile.mk
@@ -9,5 +9,6 @@ include $(top_srcdir)/src/util/logging/Makefile.mk
 include $(top_srcdir)/src/util/mem/Makefile.mk
 include $(top_srcdir)/src/util/cvar/Makefile.mk
 include $(top_srcdir)/src/util/procmap/Makefile.mk
+include $(top_srcdir)/src/util/nodemap/Makefile.mk
 include $(top_srcdir)/src/util/wrappers/Makefile.mk
 include $(top_srcdir)/src/util/assert/Makefile.mk
diff --git a/src/util/nodemap/Makefile.mk b/src/util/nodemap/Makefile.mk
new file mode 100644
index 0000000..e7756df
--- /dev/null
+++ b/src/util/nodemap/Makefile.mk
@@ -0,0 +1,12 @@
+## -*- Mode: Makefile; -*-
+## vim: set ft=automake :
+##
+## (C) 2016 by Argonne National Laboratory.
+##     See COPYRIGHT in top-level directory.
+##
+
+## FIXME check that this is the right way to do VPATH
+AM_CPPFLAGS += -I$(top_srcdir)/src/util/nodemap
+
+noinst_HEADERS +=                             \
+    src/util/nodemap/build_nodemap.h
diff --git a/src/util/nodemap/build_nodemap.h b/src/util/nodemap/build_nodemap.h
new file mode 100644
index 0000000..1c0dd82
--- /dev/null
+++ b/src/util/nodemap/build_nodemap.h
@@ -0,0 +1,515 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *  (C) 2016 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+
+#ifndef BUILD_NODEMAP_H_INCLUDED
+#define BUILD_NODEMAP_H_INCLUDED
+
+#include "mpl.h"
+
+/*
+=== BEGIN_MPI_T_CVAR_INFO_BLOCK ===
+
+cvars:
+    - name        : MPIR_CVAR_NOLOCAL
+      category    : NODEMAP
+      alt-env     : MPIR_CVAR_NO_LOCAL
+      type        : boolean
+      default     : false
+      class       : none
+      verbosity   : MPI_T_VERBOSITY_USER_BASIC
+      scope       : MPI_T_SCOPE_ALL_EQ
+      description : >-
+        If true, force all processes to operate as though all processes
+        are located on another node.  For example, this disables shared
+        memory communication hierarchical collectives.
+
+    - name        : MPIR_CVAR_ODD_EVEN_CLIQUES
+      category    : NODEMAP
+      alt-env     : MPIR_CVAR_EVEN_ODD_CLIQUES
+      type        : boolean
+      default     : false
+      class       : none
+      verbosity   : MPI_T_VERBOSITY_USER_BASIC
+      scope       : MPI_T_SCOPE_ALL_EQ
+      description : >-
+        If true, odd procs on a node are seen as local to each other, and even
+        procs on a node are seen as local to each other.  Used for debugging on
+        a single machine.
+
+=== END_MPI_T_CVAR_INFO_BLOCK ===
+*/
+
+#if !defined(USE_PMI2_API)
+/* this function is not used in pmi2 */
+#undef FUNCNAME
+#define FUNCNAME MPIR_NODEMAP_publish_node_id
+#undef FCNAME
+#define FCNAME MPL_QUOTE(FUNCNAME)
+static inline int MPIR_NODEMAP_publish_node_id(int sz, int myrank)
+{
+    int mpi_errno = MPI_SUCCESS;
+    int pmi_errno;
+    int ret;
+    char *key;
+    int key_max_sz;
+    char *kvs_name;
+    char hostname[MAX_HOSTNAME_LEN];
+    MPIR_CHKLMEM_DECL(2);
+
+    /* set hostname */
+
+    ret = gethostname(hostname, MAX_HOSTNAME_LEN);
+    MPIR_ERR_CHKANDJUMP2(ret == -1, mpi_errno, MPI_ERR_OTHER, "**sock_gethost", "**sock_gethost %s %d", MPIR_Strerror(errno), errno);
+    hostname[MAX_HOSTNAME_LEN-1] = '\0';
+
+    /* Allocate space for pmi key */
+    pmi_errno = PMI_KVS_Get_key_length_max(&key_max_sz);
+    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
+
+    MPIR_CHKLMEM_MALLOC(key, char *, key_max_sz, mpi_errno, "key");
+
+    MPIR_CHKLMEM_MALLOC(kvs_name, char *, 256, mpi_errno, "kvs_name");
+    pmi_errno = PMI_KVS_Get_my_name(kvs_name, 256);
+    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
+    /* Put my hostname id */
+    if (sz > 1)
+    {
+        memset(key, 0, key_max_sz);
+        MPL_snprintf(key, key_max_sz, "hostname[%d]", myrank);
+
+        pmi_errno = PMI_KVS_Put(kvs_name, key, hostname);
+        MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_kvs_put", "**pmi_kvs_put %d", pmi_errno);
+
+        pmi_errno = PMI_KVS_Commit(kvs_name);
+        MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_kvs_commit", "**pmi_kvs_commit %d", pmi_errno);
+
+        pmi_errno = PMI_Barrier();
+        MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_barrier", "**pmi_barrier %d", pmi_errno);
+    }
+
+fn_exit:
+    MPIR_CHKLMEM_FREEALL();
+    return mpi_errno;
+fn_fail:
+    goto fn_exit;
+}
+#endif
+
+
+#define MPIR_NODEMAP_PARSE_ERROR() MPIR_ERR_INTERNALANDJUMP(mpi_errno, "parse error")
+/* advance _c until we find a non whitespace character */
+#define MPIR_NODEMAP_SKIP_SPACE(_c) while (isspace(*(_c))) ++(_c)
+/* return true iff _c points to a character valid as an indentifier, i.e., [-_a-zA-Z0-9] */
+#define MPIR_NODEMAP_ISIDENT(_c) (isalnum(_c) || (_c) == '-' || (_c) == '_')
+
+/* give an error iff *_c != _e */
+#define MPIR_NODEMAP_EXPECT_C(_c, _e) do { if (*(_c) != _e) MPIR_NODEMAP_PARSE_ERROR(); } while (0)
+#define MPIR_NODEMAP_EXPECT_AND_SKIP_C(_c, _e) do { MPIR_NODEMAP_EXPECT_C(_c, _e); ++c; } while (0)
+/* give an error iff the first |_m| characters of the string _s are equal to _e */
+#define MPIR_NODEMAP_EXPECT_S(_s, _e) (MPL_strncmp(_s, _e, strlen(_e)) == 0 && !MPIR_NODEMAP_ISIDENT((_s)[strlen(_e)]))
+
+typedef enum {
+    MPIR_NODEMAP_UNKNOWN_MAPPING = -1,
+    MPIR_NODEMAP_NULL_MAPPING = 0,
+    MPIR_NODEMAP_VECTOR_MAPPING
+} MPIR_NODEMAP_mapping_type_t;
+
+#define MPIR_NODEMAP_VECTOR "vector"
+
+typedef struct map_block
+{
+    int start_id;
+    int count;
+    int size;
+} MPIR_NODEMAP_map_block_t;
+
+#undef FUNCNAME
+#define FUNCNAME MPIR_NODEMAP_parse_mapping
+#undef FCNAME
+#define FCNAME MPL_QUOTE(FUNCNAME)
+static inline int MPIR_NODEMAP_parse_mapping(char *map_str,
+                                             MPIR_NODEMAP_mapping_type_t *type,
+                                             MPIR_NODEMAP_map_block_t **map,
+                                             int *nblocks)
+{
+    int mpi_errno = MPI_SUCCESS;
+    char *c = map_str, *d;
+    int num_blocks = 0;
+    int i;
+    MPIR_CHKPMEM_DECL(1);
+
+    /* parse string of the form:
+       '(' <format> ',' '(' <num> ',' <num> ',' <num> ')' {',' '(' <num> ',' <num> ',' <num> ')'} ')'
+
+       the values of each 3-tuple have the following meaning (X,Y,Z):
+         X - node id start value
+         Y - number of nodes with size Z
+         Z - number of processes assigned to each node
+     */
+
+    if (!strlen(map_str)) {
+        /* An empty-string indicates an inability to determine or express the
+         * process layout on the part of the process manager.  Consider this a
+         * non-fatal error case. */
+        *type = MPIR_NODEMAP_NULL_MAPPING;
+        *map = NULL;
+        *nblocks = 0;
+        goto fn_exit;
+    }
+
+    MPIR_NODEMAP_SKIP_SPACE(c);
+    MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, '(');
+    MPIR_NODEMAP_SKIP_SPACE(c);
+
+    d = c;
+    if (MPIR_NODEMAP_EXPECT_S(d, MPIR_NODEMAP_VECTOR))
+        *type = MPIR_NODEMAP_VECTOR_MAPPING;
+    else
+        MPIR_NODEMAP_PARSE_ERROR();
+    c += strlen(MPIR_NODEMAP_VECTOR);
+    MPIR_NODEMAP_SKIP_SPACE(c);
+
+    /* first count the number of block descriptors */
+    d = c;
+    while (*d) {
+        if (*d == '(')
+            ++num_blocks;
+        ++d;
+    }
+
+    MPIR_CHKPMEM_MALLOC(*map, MPIR_NODEMAP_map_block_t *, sizeof(MPIR_NODEMAP_map_block_t) * num_blocks, mpi_errno, "map");
+
+    /* parse block descriptors */
+    for (i = 0; i < num_blocks; ++i) {
+        MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, ',');
+        MPIR_NODEMAP_SKIP_SPACE(c);
+
+        MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, '(');
+        MPIR_NODEMAP_SKIP_SPACE(c);
+
+        if (!isdigit(*c))
+            MPIR_NODEMAP_PARSE_ERROR();
+        (*map)[i].start_id = (int)strtol(c, &c, 0);
+        MPIR_NODEMAP_SKIP_SPACE(c);
+
+        MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, ',');
+        MPIR_NODEMAP_SKIP_SPACE(c);
+
+        if (!isdigit(*c))
+            MPIR_NODEMAP_PARSE_ERROR();
+        (*map)[i].count = (int)strtol(c, &c, 0);
+        MPIR_NODEMAP_SKIP_SPACE(c);
+
+        MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, ',');
+        MPIR_NODEMAP_SKIP_SPACE(c);
+
+        if (!isdigit(*c))
+            MPIR_NODEMAP_PARSE_ERROR();
+        (*map)[i].size = (int)strtol(c, &c, 0);
+
+        MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, ')');
+        MPIR_NODEMAP_SKIP_SPACE(c);
+    }
+
+    MPIR_NODEMAP_EXPECT_AND_SKIP_C(c, ')');
+
+    *nblocks = num_blocks;
+    MPIR_CHKPMEM_COMMIT();
+fn_exit:
+    return mpi_errno;
+fn_fail:
+    /* --BEGIN ERROR HANDLING-- */
+    MPIR_CHKPMEM_REAP();
+    goto fn_exit;
+    /* --END ERROR HANDLING-- */
+}
+
+#undef FUNCNAME
+#define FUNCNAME MPIR_NODEMAP_populate_ids_from_mapping
+#undef FCNAME
+#define FCNAME MPL_QUOTE(FUNCNAME)
+static inline int MPIR_NODEMAP_populate_ids_from_mapping(char *mapping,
+                                                         int sz,
+                                                         MPID_Node_id_t *out_nodemap,
+                                                         MPID_Node_id_t *max_node_id,
+                                                         int *did_map)
+{
+    int mpi_errno = MPI_SUCCESS;
+    /* PMI_process_mapping is available */
+    MPIR_NODEMAP_mapping_type_t mt = MPIR_NODEMAP_UNKNOWN_MAPPING;
+    MPIR_NODEMAP_map_block_t *mb = NULL;
+    int nblocks = 0;
+    int rank;
+    int block, block_node, node_proc;
+    int i;
+    int found_wrap;
+
+    *did_map = 1; /* reset upon failure */
+
+    mpi_errno = MPIR_NODEMAP_parse_mapping(mapping, &mt, &mb, &nblocks);
+    if (mpi_errno) MPIR_ERR_POP(mpi_errno);
+
+    if (MPIR_NODEMAP_NULL_MAPPING == mt) goto fn_fail;
+    MPIR_ERR_CHKINTERNAL(mt != MPIR_NODEMAP_VECTOR_MAPPING, mpi_errno, "unsupported mapping type");
+
+    /* allocate nodes to ranks */
+    found_wrap = 0;
+    for (rank = 0;;) {
+        /* FIXME: The patch is hacky because it assumes that seeing a
+         * start node ID of 0 means a wrap around.  This is not
+         * necessarily true.  A user-defined node list can, in theory,
+         * use the node ID 0 without actually creating a wrap around.
+         * The reason this patch still works in this case is because
+         * Hydra creates a new node list starting from node ID 0 for
+         * user-specified nodes during MPI_Comm_spawn{_multiple}.  If
+         * a different process manager searches for allocated nodes in
+         * the user-specified list, this patch will break. */
+
+        /* If we found that the blocks wrap around, repeat loops
+         * should only start at node id 0 */
+        for (block = 0; found_wrap && mb[block].start_id; block++);
+
+        for (; block < nblocks; block++) {
+            if (mb[block].start_id == 0)
+                found_wrap = 1;
+            for (block_node = 0; block_node < mb[block].count; block_node++) {
+                for (node_proc = 0; node_proc < mb[block].size; node_proc++) {
+                    out_nodemap[rank]= mb[block].start_id + block_node;
+                    if (++rank == sz)
+                        goto break_out;
+                }
+            }
+        }
+    }
+
+ break_out:
+    /* identify maximum node id */
+    *max_node_id = -1;
+    for (i = 0; i < sz; i++)
+        if (out_nodemap[i] + 1 > *max_node_id)
+            *max_node_id = out_nodemap[i];
+
+fn_exit:
+    MPL_free(mb);
+    return mpi_errno;
+fn_fail:
+    /* --BEGIN ERROR HANDLING-- */
+    *did_map = 0;
+    goto fn_exit;
+    /* --END ERROR HANDLING-- */
+}
+
+/* Fills in the node_id info from PMI info.  Adapted from MPIU_Get_local_procs.
+   This function is collective over the entire PG because PMI_Barrier is called.
+
+   myrank should be set to -1 if this is not the current process' PG.  This
+   is currently not supported due to PMI limitations.
+
+   Fallback Algorithm:
+
+   Each process kvs_puts its hostname and stores the total number of
+   processes (g_num_global).  Each process determines maximum node id
+   (g_max_node_id) and assigns a node id to each process (g_node_ids[]):
+
+     For each hostname the process seaches the list of unique nodes
+     names (node_names[]) for a match.  If a match is found, the node id
+     is recorded for that matching process.  Otherwise, the hostname is
+     added to the list of node names.
+*/
+#undef FUNCNAME
+#define FUNCNAME MPIR_NODEMAP_build_nodemap
+#undef FCNAME
+#define FCNAME MPL_QUOTE(FUNCNAME)
+static inline int MPIR_NODEMAP_build_nodemap(int sz,
+                                             int myrank,
+                                             MPID_Node_id_t *out_nodemap,
+                                             MPID_Node_id_t *out_sz)
+{
+    static int g_max_node_id = -1;
+    int mpi_errno = MPI_SUCCESS;
+    int pmi_errno;
+    int i, j;
+    char *key;
+    char *value;
+    int key_max_sz;
+    int val_max_sz;
+    char *kvs_name;
+    char **node_names;
+    char *node_name_buf;
+    int no_local = 0;
+    int odd_even_cliques = 0;
+    int pmi_version = 1;
+    int pmi_subversion = 1;
+    MPIR_CHKLMEM_DECL(5);
+
+    /* See if the user wants to override our default values */
+    MPL_env2int("PMI_VERSION", &pmi_version);
+    MPL_env2int("PMI_SUBVERSION", &pmi_subversion);
+
+    if (sz == 1) {
+        out_nodemap[0] = ++g_max_node_id;
+        *out_sz = g_max_node_id;
+        goto fn_exit;
+    }
+
+    /* Used for debugging only.  This disables communication over shared memory */
+#ifdef ENABLED_NO_LOCAL
+    no_local = 1;
+#else
+    no_local = MPIR_CVAR_NOLOCAL;
+#endif
+
+    /* Used for debugging on a single machine: Odd procs on a node are
+       seen as local to each other, and even procs on a node are seen
+       as local to each other. */
+#ifdef ENABLED_ODD_EVEN_CLIQUES
+    odd_even_cliques = 1;
+#else
+    odd_even_cliques = MPIR_CVAR_ODD_EVEN_CLIQUES;
+#endif
+
+    if (no_local) {
+        /* just assign 0 to n-1 as node ids and bail */
+        for (i = 0; i < sz; ++i) {
+            out_nodemap[i] = ++g_max_node_id;
+        }
+        *out_sz = g_max_node_id;
+        goto fn_exit;
+    }
+
+#ifdef USE_PMI2_API
+    {
+        char process_mapping[PMI2_MAX_VALLEN];
+        int outlen;
+        int found = FALSE;
+        int i;
+        MPIR_NODEMAP_map_block_t *mb;
+        int nblocks;
+        int rank;
+        int block, block_node, node_proc;
+        int did_map = 0;
+
+        mpi_errno = PMI2_Info_GetJobAttr("PMI_process_mapping", process_mapping, sizeof(process_mapping), &found);
+        if (mpi_errno) MPIR_ERR_POP(mpi_errno);
+        MPIR_ERR_CHKINTERNAL(!found, mpi_errno, "PMI_process_mapping attribute not found");
+        /* this code currently assumes pg is comm_world */
+        mpi_errno = MPIR_NODEMAP_populate_ids_from_mapping(process_mapping, sz, out_nodemap, out_sz, &did_map);
+        if (mpi_errno) MPIR_ERR_POP(mpi_errno);
+        MPIR_ERR_CHKINTERNAL(!did_map, mpi_errno, "unable to populate node ids from PMI_process_mapping");
+    }
+#else /* USE_PMI2_API */
+    if (myrank == -1) {
+        /* fixme this routine can't handle the dynamic process case at this
+           time.  this will require more support from the process manager. */
+        MPIR_Assert(0);
+    }
+
+    /* Allocate space for pmi key and value */
+    pmi_errno = PMI_KVS_Get_key_length_max(&key_max_sz);
+    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
+    MPIR_CHKLMEM_MALLOC(key, char *, key_max_sz, mpi_errno, "key");
+
+    pmi_errno = PMI_KVS_Get_value_length_max(&val_max_sz);
+    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
+    MPIR_CHKLMEM_MALLOC(value, char *, val_max_sz, mpi_errno, "value");
+
+    MPIR_CHKLMEM_MALLOC(kvs_name, char *, 256, mpi_errno, "kvs_name");
+    pmi_errno = PMI_KVS_Get_my_name(kvs_name, 256);
+    MPIR_ERR_CHKANDJUMP1(pmi_errno, mpi_errno, MPI_ERR_OTHER, "**fail", "**fail %d", pmi_errno);
+    /* See if process manager supports PMI_process_mapping keyval */
+
+    if (pmi_version == 1 && pmi_subversion == 1) {
+        pmi_errno = PMI_KVS_Get(kvs_name, "PMI_process_mapping", value, val_max_sz);
+        if (pmi_errno == 0) {
+            int did_map = 0;
+            /* this code currently assumes pg is comm_world */
+            mpi_errno = MPIR_NODEMAP_populate_ids_from_mapping(value, sz, out_nodemap, out_sz, &did_map);
+            g_max_node_id = *out_sz;
+            if (mpi_errno) MPIR_ERR_POP(mpi_errno);
+            if (did_map) {
+                goto odd_even_cliques;
+            }
+            /* else fall through to O(N^2) PMI_KVS_Gets version */
+        }
+    }
+
+    /* fallback algorithm */
+    mpi_errno = MPIR_NODEMAP_publish_node_id(sz, myrank);
+    if (mpi_errno) MPIR_ERR_POP(mpi_errno);
+
+    /* Allocate temporary structures.  These would need to be persistent if
+       we somehow were able to support dynamic processes via this method. */
+    MPIR_CHKLMEM_MALLOC(node_names, char **, sz * sizeof(char*), mpi_errno, "node_names");
+    MPIR_CHKLMEM_MALLOC(node_name_buf, char *, sz * key_max_sz * sizeof(char), mpi_errno, "node_name_buf");
+
+    /* Gather hostnames */
+    for (i = 0; i < sz; ++i)
+    {
+        node_names[i] = &node_name_buf[i * key_max_sz];
+        node_names[i][0] = '\0';
+    }
+
+    g_max_node_id = -1; /* defensive */
+
+    for (i = 0; i < sz; ++i)
+    {
+        MPIR_Assert(g_max_node_id < sz);
+        if (i == myrank)
+        {
+            /* This is us, no need to perform a get */
+            int ret;
+            char *hostname = (char*) MPL_malloc(sizeof(char) * MAX_HOSTNAME_LEN);
+            ret = gethostname(hostname, MAX_HOSTNAME_LEN);
+            MPIR_ERR_CHKANDJUMP2(ret == -1, mpi_errno, MPI_ERR_OTHER, "**sock_gethost", "**sock_gethost %s %d", MPIR_Strerror(errno), errno);
+            hostname[MAX_HOSTNAME_LEN-1] = '\0';
+            MPL_snprintf(node_names[g_max_node_id+1], key_max_sz, "%s", hostname);
+            MPL_free(hostname);
+        }
+        else
+        {
+            memset(key, 0, key_max_sz);
+            MPL_snprintf(key, key_max_sz, "hostname[%d]", i);
+
+            pmi_errno = PMI_KVS_Get(kvs_name, key, node_names[g_max_node_id+1], key_max_sz);
+            MPIR_ERR_CHKANDJUMP1(pmi_errno != PMI_SUCCESS, mpi_errno, MPI_ERR_OTHER, "**pmi_kvs_get", "**pmi_kvs_get %d", pmi_errno);
+        }
+
+        /* Find the node_id for this process, or create a new one */
+        /* FIXME:need a better algorithm -- this one does O(N^2) strncmp()s! */
+        /* The right fix is to get all this information from the process
+           manager, rather than bother with this hostname hack at all. */
+        for (j = 0; j < g_max_node_id + 1; ++j)
+            if (!MPL_strncmp(node_names[j], node_names[g_max_node_id+1], key_max_sz))
+                break;
+        if (j == g_max_node_id + 1)
+            ++g_max_node_id;
+        else
+            node_names[g_max_node_id+1][0] = '\0';
+        out_nodemap[i] = j;
+    }
+
+odd_even_cliques:
+    if (odd_even_cliques)
+    {
+        /* Create new processes for all odd numbered processes. This
+           may leave nodes ids with no processes assigned to them, but
+           I think this is OK */
+        for (i = 0; i < sz; ++i)
+            if (i & 0x1)
+                out_nodemap[i] += g_max_node_id + 1;
+        g_max_node_id = (g_max_node_id + 1) * 2;
+    }
+    *out_sz = g_max_node_id;
+#endif
+
+fn_exit:
+    MPIR_CHKLMEM_FREEALL();
+    return mpi_errno;
+fn_fail:
+    goto fn_exit;
+}
+
+#endif /* ifndef BUILD_NODEMAP_H_INCLUDED */

http://git.mpich.org/mpich.git/commitdiff/355a3e01c52f914d235a6a387dd0e13a6fcc6f8f

commit 355a3e01c52f914d235a6a387dd0e13a6fcc6f8f
Author: Ken Raffenetti <raffenet at mcs.anl.gov>
Date:   Mon Apr 11 13:12:41 2016 -0500

    Guard datatype macro definitions
    
    These macros have a tendency to show up in other parts of the code
    that deal with MPI_Datatype (i.e. not MPIR_Datatype). Guard their
    definition to avoid duplicate warnings at compile time.
    
    Signed-off-by: Charles J Archer <charles.j.archer at intel.com>

diff --git a/src/mpid/common/sched/mpidu_sched.c b/src/mpid/common/sched/mpidu_sched.c
index bc72332..5225feb 100644
--- a/src/mpid/common/sched/mpidu_sched.c
+++ b/src/mpid/common/sched/mpidu_sched.c
@@ -21,6 +21,7 @@
 /* helper macros to improve code readability */
 /* we pessimistically assume that MPI_DATATYPE_NULL may be passed as a "valid" type
  * for send/recv when MPI_PROC_NULL is the destination/src */
+#ifndef dtype_add_ref_if_not_builtin
 #define dtype_add_ref_if_not_builtin(datatype_)                    \
     do {                                                           \
         if ((datatype_) != MPI_DATATYPE_NULL &&                    \
@@ -31,6 +32,8 @@
             MPID_Datatype_add_ref(dtp_);                           \
         }                                                          \
     } while (0)
+#endif
+#ifndef dtype_release_if_not_builtin
 #define dtype_release_if_not_builtin(datatype_)                    \
     do {                                                           \
         if ((datatype_) != MPI_DATATYPE_NULL &&                    \
@@ -41,6 +44,7 @@
             MPID_Datatype_release(dtp_);                           \
         }                                                          \
     } while (0)
+#endif
 
 /* TODO move to a header somewhere? */
 void MPIDU_Sched_dump(struct MPIDU_Sched *s);

-----------------------------------------------------------------------

Summary of changes:
 src/mpid/ch3/src/mpid_vc.c          |  528 +----------------------------------
 src/mpid/common/sched/mpidu_sched.c |    4 +
 src/util/Makefile.mk                |    1 +
 src/util/nodemap/Makefile.mk        |   12 +
 src/util/nodemap/build_nodemap.h    |  515 ++++++++++++++++++++++++++++++++++
 5 files changed, 541 insertions(+), 519 deletions(-)
 create mode 100644 src/util/nodemap/Makefile.mk
 create mode 100644 src/util/nodemap/build_nodemap.h


hooks/post-receive
-- 
MPICH primary repository


More information about the commits mailing list