root/opal/mca/pmix/pmix4x/pmix/contrib/perf_tools/pmi2_pmap_parser.c

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

DEFINITIONS

This source file includes following definitions.
  1. find_my_node
  2. find_lrs
  3. mca_common_pmi2_parse_pmap
  4. dump_lrs
  5. main

   1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
   2 /*
   3  *
   4  * Copyright (c) 2013      Mellanox Technologies, Inc.
   5  *                         All rights reserved.
   6  * Copyright (c) 2014-2016 Intel, Inc.  All rights reserved.
   7  * $COPYRIGHT$
   8  * Additional copyrights may follow
   9  *
  10  * $HEADER$
  11  *
  12  */
  13 
  14 /* This code was taken from Open MPI project, file
  15    opal/mca/pmix/s2/pmi2_pmap_parser.c
  16 */
  17 
  18 #include "pmi2_pmap_parser.h"
  19 
  20 /**
  21  pmi2 process mapping is returned as a
  22  comma separated list of tuples:
  23 ex: (vector,(0,4,4),(0,4,1))
  24 slurm cyclic distro of 4 ranks over 2 nodes:
  25 (vector,(0,2,1),(0,2,1))
  26 slurm block distro of 4 ranks over 2 nodes:
  27 (vector,(0,2,2))
  28 
  29 
  30  Format of each tuple is (base, H, L), where
  31  H is number of nodes spawned by tuple,
  32  L is number of ranks per node,
  33  base is offset from node 0.
  34 
  35  Tuple can be visualized as a rectangle on two
  36  dimensional (Hosts, Local Ranks) plane:
  37 
  38            ------------------------------------ Hosts ->
  39            |              H
  40            |           +--------+
  41            |<- base -->|        |
  42            |           |        | L
  43            |           +--------+
  44         Local Ranks
  45            V
  46 
  47 Note that ranks increase by column. Tuple (0,2,3) looks like:
  48 0 3
  49 1 4
  50 2 5
  51 
  52 */
  53 #include <stdio.h>
  54 #include <stdlib.h>
  55 #include <string.h>
  56 static int find_my_node(char *map, int me)
  57 {
  58     int abs_rank;
  59     int base, H, L;
  60     char *p;
  61 
  62     p = map;
  63     abs_rank = 0;
  64     while (NULL != (p = strstr(p+1, ",("))) {
  65         if (3 != sscanf(p, ",(%d,%d,%d)", &base, &H, &L)) {
  66             return -1;
  67         }
  68         if (me >= abs_rank && me < abs_rank + H*L) {
  69             /* found my rectangle, compute node */
  70             return base + (me - abs_rank)/L;
  71         }
  72         abs_rank += H*L;
  73     }
  74     return -1;
  75 }
  76 
  77 static int *find_lrs(char *map, int my_node, int *nlrs)
  78 {
  79     int abs_rank;
  80     int base, H, L;
  81     char *p;
  82     int *lrs;
  83     int max_lr;
  84     int i;
  85 
  86     p = map;
  87     abs_rank = 0;
  88     *nlrs = 0;
  89     max_lr = 16;
  90     lrs = malloc(max_lr * sizeof(int));
  91     while (NULL != (p = strstr(p+1, ",("))) {
  92         if (3 != sscanf(p, ",(%d,%d,%d)", &base, &H, &L)) {
  93             free(lrs);
  94             return NULL;
  95         }
  96         if (base <= my_node && my_node < base + H) {
  97             if (*nlrs + L >= max_lr) {
  98                 lrs = realloc(lrs, (max_lr + L) * sizeof(int));
  99                 if (NULL == lrs) {
 100                     *nlrs = 0;
 101                     free(lrs);
 102                     return NULL;
 103                 }
 104                 max_lr += L;
 105             }
 106             /* skip (my_node - base) columns of L elems,
 107              * numbers in my column are local to me
 108              */
 109             for (i = 0; i < L; i++) {
 110                 lrs[*nlrs] = (my_node - base) * L + i + abs_rank;
 111                 (*nlrs) ++;
 112             }
 113         }
 114         abs_rank += H*L;
 115     }
 116 
 117     if (0 == *nlrs) {
 118         free(lrs);
 119         lrs = 0;
 120     }
 121     return lrs;
 122 }
 123 
 124 /**
 125  * @param pmap process map as returned by PMI_process_mapping
 126  *             attribute
 127  * @param my_rank
 128  * @param node set to my node id
 129  * @param nlrs set to the number of local ranks returned
 130  *
 131  * @return array that contains ranks local to my_rank or NULL
 132  * on failure. Array must be freed by the caller.
 133  */
 134 int *mca_common_pmi2_parse_pmap(char *pmap, int my_rank,
 135                                   int *node, int *nlrs)
 136 {
 137     char *p;
 138 
 139     p = strstr(pmap, "(vector");
 140     if (NULL == p) {
 141         return NULL;
 142     }
 143 
 144     *node = find_my_node(p, my_rank);
 145     if (0 > *node) {
 146        return NULL;
 147     }
 148 
 149     return find_lrs(p, *node, nlrs);
 150 }
 151 
 152 
 153 #ifdef STANDALONE_TEST
 154 #include <assert.h>
 155 static void dump_lrs(int *lrs, int me, int node, int n)
 156 {
 157     int i;
 158 
 159     printf("Total %d ranks/node, node %d me %d\n", n, node, me);
 160     for (i = 0; i < n; i++) {
 161         printf("%d ", lrs[i]);
 162     }
 163     printf("\n");
 164     free(lrs);
 165 }
 166 
 167 int main(int argc, char **argv)
 168 {
 169     int me, n, node;
 170     int *lrs;
 171     char *pmap;
 172     int a1[] = {0, 1};
 173     int a2[] = {2, 3};
 174     int a3[] = {0, 2};
 175     int a4[] = {1, 3};
 176     int a5[] = {0,1,3,2,16,17};
 177     int a6[] = {8,9,10,11,19};
 178 
 179 
 180     if (argc == 3) {
 181         me = atoi(argv[1]);
 182         lrs = orte_grpcomm_pmi2_parse_pmap(argv[2], me, &node, &n);
 183         if (NULL == lrs) {
 184             printf("can not parse pmap\n");
 185             exit(1);
 186         }
 187         dump_lrs(lrs, me, node, n);
 188         exit(0);
 189     }
 190     /* built in cases */
 191 
 192     pmap = "(vector,(0,2,2))";
 193     me = 1;
 194     lrs = orte_grpcomm_pmi2_parse_pmap(pmap, me, &node, &n);
 195     assert(lrs);
 196     assert(n == 2);
 197     assert(memcmp(lrs, a1, 2) == 0);
 198     free(lrs);
 199 
 200 
 201     pmap = "(vector,(0,2,2))";
 202     me = 2;
 203     lrs = orte_grpcomm_pmi2_parse_pmap(pmap, me, &node, &n);
 204     assert(lrs);
 205     assert(n == 2);
 206     assert(memcmp(lrs, a2, 2) == 0);
 207     free(lrs);
 208 
 209 
 210     /* cyclic distro which skips node 0 */
 211     pmap = "(vector,(1,2,1),(1,2,1))";
 212     me = 0;
 213     lrs = orte_grpcomm_pmi2_parse_pmap(pmap, me, &node, &n);
 214     assert(lrs);
 215     assert(n == 2);
 216     assert(memcmp(lrs, a3, n) == 0);
 217     free(lrs);
 218 
 219     pmap = "(vector,(1,2,1),(1,2,1))";
 220     me = 3;
 221     lrs = orte_grpcomm_pmi2_parse_pmap(pmap, me, &node, &n);
 222     assert(lrs);
 223     assert(n == 2);
 224     assert(memcmp(lrs, a4, n) == 0);
 225     free(lrs);
 226 
 227     pmap = "(vector,(0,4,4),(0,1,2),(1,3,1))";
 228     me = 3;
 229     lrs = orte_grpcomm_pmi2_parse_pmap(pmap, me, &node, &n);
 230     assert(lrs);
 231     assert(n == 6);
 232     assert(memcmp(lrs, a5, n) == 0);
 233     free(lrs);
 234 
 235     pmap = "(vector,(0,4,4),(0,1,2),(1,3,1))";
 236     me = 10;
 237     lrs = orte_grpcomm_pmi2_parse_pmap(pmap, me, &node, &n);
 238     assert(lrs);
 239     assert(n == 5);
 240     assert(memcmp(lrs, a6, n) == 0);
 241     free(lrs);
 242     return 0;
 243 }
 244 #endif

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