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

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