1 #if HAVE_CONFIG_H
2 #   include "config.h"
3 #endif
4 
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 
11 #include <mpi.h>
12 
13 #if defined(__bgp__)
14 #include <spi/kernel_interface.h>
15 #include <common/bgp_personality.h>
16 #include <common/bgp_personality_inlines.h>
17 #elif defined(__bgq__)
18 #  include <mpix.h>
19 #elif defined(__CRAYXT) || defined(__CRAYXE)
20 #  include <pmi.h>
21 #endif
22 
23 #include "comex.h"
24 #include "comex_impl.h"
25 #include "groups.h"
26 
27 
28 /* world group state */
29 comex_group_world_t g_state = {
30     MPI_COMM_NULL,
31     MPI_GROUP_NULL,
32     -1,
33     -1,
34     NULL,
35     NULL,
36     MPI_COMM_NULL,
37     -1,
38     -1
39 };
40 /* the HEAD of the group linked list */
41 comex_igroup_t *group_list = NULL;
42 
43 #define RANK_OR_PID (g_state.rank >= 0 ? g_state.rank : getpid())
44 
45 /* static functions implemented in this file */
46 static void _create_group_and_igroup(comex_group_t *id, comex_igroup_t **igroup);
47 static void _igroup_free(comex_igroup_t *igroup);
48 static long xgethostid();
49 
50 
51 /**
52  * Return the comex igroup instance given the group id.
53  *
54  * The group linked list is searched sequentially until the given group
55  * is found. It is an error if this function is called before
56  * comex_group_init(). An error occurs if the given group is not found.
57  */
comex_get_igroup_from_group(comex_group_t id)58 comex_igroup_t* comex_get_igroup_from_group(comex_group_t id)
59 {
60     comex_igroup_t *current_group_list_item = group_list;
61 
62 #if DEBUG
63     printf("[%d] comex_get_igroup_from_group(%d)\n", RANK_OR_PID, id);
64 #endif
65 
66     COMEX_ASSERT(group_list != NULL);
67     while (current_group_list_item != NULL) {
68         if (current_group_list_item->id == id) {
69             return current_group_list_item;
70         }
71         current_group_list_item = current_group_list_item->next;
72     }
73     comex_error("comex group lookup failed", -1);
74 
75     return NULL;
76 }
77 
78 
79 /**
80  * Creates and associates a comex group with a comex igroup.
81  *
82  * This does *not* initialize the members of the comex igroup.
83  */
_create_group_and_igroup(comex_group_t * id,comex_igroup_t ** igroup)84 static void _create_group_and_igroup(
85         comex_group_t *id, comex_igroup_t **igroup)
86 {
87     comex_igroup_t *new_group_list_item = NULL;
88     comex_igroup_t *last_group_list_item = NULL;
89 
90 #if DEBUG
91     printf("[%d] _create_group_and_igroup(...)\n", RANK_OR_PID);
92 #endif
93 
94     /* create, init, and insert the new node for the linked list */
95     new_group_list_item = malloc(sizeof(comex_igroup_t));
96     new_group_list_item->next = NULL;
97     new_group_list_item->id = -1;
98     new_group_list_item->comm = MPI_COMM_NULL;
99     new_group_list_item->group = MPI_GROUP_NULL;
100     new_group_list_item->size = -1;
101     new_group_list_item->rank = -1;
102     new_group_list_item->world_ranks = NULL;
103 
104     /* find the last group in the group linked list and insert */
105     if (group_list) {
106         last_group_list_item = group_list;
107         while (last_group_list_item->next != NULL) {
108             last_group_list_item = last_group_list_item->next;
109         }
110         last_group_list_item->next = new_group_list_item;
111         new_group_list_item->id = last_group_list_item->id + 1;
112     }
113     else {
114         group_list = new_group_list_item;
115         new_group_list_item->id = COMEX_GROUP_WORLD;
116     }
117 
118     /* return the group id and comex igroup */
119     *igroup = new_group_list_item;
120     *id = new_group_list_item->id;
121 }
122 
123 
comex_group_rank(comex_group_t group,int * rank)124 int comex_group_rank(comex_group_t group, int *rank)
125 {
126     comex_igroup_t *igroup = comex_get_igroup_from_group(group);
127     *rank = igroup->rank;
128 
129 #if DEBUG
130     printf("[%d] comex_group_rank(group=%d, *rank=%d)\n",
131             RANK_OR_PID, group, *rank);
132 #endif
133 
134     return COMEX_SUCCESS;
135 }
136 
137 
comex_group_size(comex_group_t group,int * size)138 int comex_group_size(comex_group_t group, int *size)
139 {
140     comex_igroup_t *igroup = comex_get_igroup_from_group(group);
141     *size = igroup->size;
142 
143 #if DEBUG
144     printf("[%d] comex_group_size(group=%d, *size=%d)\n",
145             RANK_OR_PID, group, *size);
146 #endif
147 
148     return COMEX_SUCCESS;
149 }
150 
151 
comex_group_comm(comex_group_t group,MPI_Comm * comm)152 int comex_group_comm(comex_group_t group, MPI_Comm *comm)
153 {
154     comex_igroup_t *igroup = comex_get_igroup_from_group(group);
155     *comm = igroup->comm;
156 
157 #if DEBUG
158     printf("[%d] comex_group_comm(group=%d, comm)\n",
159             RANK_OR_PID, group);
160 #endif
161 
162     return COMEX_SUCCESS;
163 }
164 
165 
comex_group_translate_world(comex_group_t group,int group_rank,int * world_rank)166 int comex_group_translate_world(
167         comex_group_t group, int group_rank, int *world_rank)
168 {
169 #if DEBUG
170     printf("[%d] comex_group_translate_world("
171             "group=%d, group_rank=%d, world_rank)\n",
172             RANK_OR_PID, group, group_rank);
173 #endif
174 
175     if (COMEX_GROUP_WORLD == group) {
176         *world_rank = group_rank;
177     }
178     else {
179         int status;
180         comex_igroup_t *igroup = comex_get_igroup_from_group(group);
181 
182         COMEX_ASSERT(group_list); /* first group is world worker group */
183         status = MPI_Group_translate_ranks(igroup->group, 1, &group_rank,
184                 group_list->group, world_rank);
185     }
186 
187     return COMEX_SUCCESS;
188 }
189 
190 
191 /**
192  * Destroys the given comex igroup.
193  */
_igroup_free(comex_igroup_t * igroup)194 static void _igroup_free(comex_igroup_t *igroup)
195 {
196     int status;
197 
198 #if DEBUG
199     printf("[%d] _igroup_free\n",
200             RANK_OR_PID);
201 #endif
202 
203     COMEX_ASSERT(igroup);
204 
205     if (igroup->group != MPI_GROUP_NULL) {
206         status = MPI_Group_free(&igroup->group);
207         if (status != MPI_SUCCESS) {
208             comex_error("MPI_Group_free: Failed ", status);
209         }
210     }
211 #if DEBUG
212     printf("[%d] free'd group\n", RANK_OR_PID);
213 #endif
214 
215     if (igroup->comm != MPI_COMM_NULL) {
216         status = MPI_Comm_free(&igroup->comm);
217         if (status != MPI_SUCCESS) {
218             comex_error("MPI_Comm_free: Failed ", status);
219         }
220     }
221 #if DEBUG
222     printf("[%d] free'd comm\n", RANK_OR_PID);
223 #endif
224     if (igroup->world_ranks != NULL) {
225       free(igroup->world_ranks);
226     }
227 
228     free(igroup);
229 }
230 
231 
comex_group_free(comex_group_t id)232 int comex_group_free(comex_group_t id)
233 {
234     comex_igroup_t *current_group_list_item = group_list;
235     comex_igroup_t *previous_group_list_item = NULL;
236 
237 #if DEBUG
238     printf("[%d] comex_group_free(id=%d)\n", RANK_OR_PID, id);
239 #endif
240 
241     /* find the group to free */
242     while (current_group_list_item != NULL) {
243         if (current_group_list_item->id == id) {
244             break;
245         }
246         previous_group_list_item = current_group_list_item;
247         current_group_list_item = current_group_list_item->next;
248     }
249     /* make sure we found a group */
250     COMEX_ASSERT(current_group_list_item != NULL);
251     /* remove the group from the linked list */
252     if (previous_group_list_item != NULL) {
253         previous_group_list_item->next = current_group_list_item->next;
254     }
255     /* free the igroup */
256     _igroup_free(current_group_list_item);
257 
258     return COMEX_SUCCESS;
259 }
260 
_igroup_set_world_ranks(comex_igroup_t * igroup)261 void _igroup_set_world_ranks(comex_igroup_t *igroup)
262 {
263   int i = 0;
264   int my_world_rank = g_state.rank;
265   igroup->world_ranks = (int*)malloc(sizeof(int)*igroup->size);
266   int status;
267 
268   for (i=0; i<igroup->size; ++i) {
269     igroup->world_ranks[i] = MPI_PROC_NULL;
270   }
271 
272   status = MPI_Allgather(&my_world_rank,1,MPI_INT,igroup->world_ranks,
273       1,MPI_INT,igroup->comm);
274   COMEX_ASSERT(MPI_SUCCESS == status);
275 
276   for (i=0; i<igroup->size; ++i) {
277     COMEX_ASSERT(MPI_PROC_NULL != igroup->world_ranks[i]);
278   }
279 }
280 
comex_group_create(int n,int * pid_list,comex_group_t id_parent,comex_group_t * id_child)281 int comex_group_create(
282         int n, int *pid_list, comex_group_t id_parent, comex_group_t *id_child)
283 {
284     int status = 0;
285     int grp_me = 0;
286     comex_igroup_t *igroup_child = NULL;
287     MPI_Group      *group_child = NULL;
288     MPI_Comm       *comm_child = NULL;
289     comex_igroup_t *igroup_parent = NULL;
290     MPI_Group      *group_parent = NULL;
291     MPI_Comm       *comm_parent = NULL;
292 
293 #if DEBUG
294     printf("[%d] comex_group_create("
295             "n=%d, pid_list=%p, id_parent=%d, id_child)\n",
296             RANK_OR_PID, n, pid_list, id_parent);
297     {
298         int p;
299         printf("[%d] pid_list={%d", RANK_OR_PID, pid_list[0]);
300         for (p=1; p<n; ++p) {
301             printf(",%d", pid_list[p]);
302         }
303         printf("}\n");
304     }
305 #endif
306 
307     /* create the node in the linked list of groups and */
308     /* get the child's MPI_Group and MPI_Comm, to be populated shortly */
309     _create_group_and_igroup(id_child, &igroup_child);
310     group_child = &(igroup_child->group);
311     comm_child  = &(igroup_child->comm);
312 
313     /* get the parent's MPI_Group and MPI_Comm */
314     igroup_parent = comex_get_igroup_from_group(id_parent);
315     group_parent = &(igroup_parent->group);
316     comm_parent  = &(igroup_parent->comm);
317 
318     status = MPI_Group_incl(*group_parent, n, pid_list, group_child);
319     COMEX_ASSERT(MPI_SUCCESS == status);
320 
321 #if DEBUG
322     printf("[%d] comex_group_create before crazy logic\n", RANK_OR_PID);
323 #endif
324     {
325         MPI_Comm comm, comm1, comm2;
326         int lvl=1, local_ldr_pos;
327         status = MPI_Group_rank(*group_child, &grp_me);
328         COMEX_ASSERT(MPI_SUCCESS == status);
329         if (grp_me == MPI_UNDEFINED) {
330             /* FIXME: keeping the group around for now */
331 #if DEBUG
332     printf("[%d] comex_group_create aborting -- not in group\n", RANK_OR_PID);
333 #endif
334             return COMEX_SUCCESS;
335         }
336         /* SK: sanity check for the following bitwise operations */
337         COMEX_ASSERT(grp_me>=0);
338         /* FIXME: can be optimized away */
339         status = MPI_Comm_dup(MPI_COMM_SELF, &comm);
340         COMEX_ASSERT(MPI_SUCCESS == status);
341         local_ldr_pos = grp_me;
342         while(n>lvl) {
343             int tag=0;
344             int remote_ldr_pos = local_ldr_pos^lvl;
345             if (remote_ldr_pos < n) {
346                 int remote_leader = pid_list[remote_ldr_pos];
347                 MPI_Comm peer_comm = *comm_parent;
348                 int high = (local_ldr_pos<remote_ldr_pos)?0:1;
349                 status = MPI_Intercomm_create(
350                         comm, 0, peer_comm, remote_leader, tag, &comm1);
351                 COMEX_ASSERT(MPI_SUCCESS == status);
352                 status = MPI_Comm_free(&comm);
353                 COMEX_ASSERT(MPI_SUCCESS == status);
354                 status = MPI_Intercomm_merge(comm1, high, &comm2);
355                 COMEX_ASSERT(MPI_SUCCESS == status);
356                 status = MPI_Comm_free(&comm1);
357                 COMEX_ASSERT(MPI_SUCCESS == status);
358                 comm = comm2;
359             }
360             local_ldr_pos &= ((~0)^lvl);
361             lvl<<=1;
362         }
363         *comm_child = comm;
364         /* cleanup temporary group (from MPI_Group_incl above) */
365         status = MPI_Group_free(group_child);
366         COMEX_ASSERT(MPI_SUCCESS == status);
367         /* get the actual group associated with comm */
368         status = MPI_Comm_group(*comm_child, group_child);
369         COMEX_ASSERT(MPI_SUCCESS == status);
370         /* rank and size of new comm */
371         status = MPI_Comm_size(igroup_child->comm, &(igroup_child->size));
372         COMEX_ASSERT(MPI_SUCCESS == status);
373         status = MPI_Comm_rank(igroup_child->comm, &(igroup_child->rank));
374         COMEX_ASSERT(MPI_SUCCESS == status);
375     }
376 #if DEBUG
377     printf("[%d] comex_group_create after crazy logic\n", RANK_OR_PID);
378 #endif
379     _igroup_set_world_ranks(igroup_child);
380 
381     return COMEX_SUCCESS;
382 }
383 
384 
cmplong(const void * p1,const void * p2)385 static int cmplong(const void *p1, const void *p2)
386 {
387     return *((long*)p1) - *((long*)p2);
388 }
389 
390 /**
391  * Initialize group linked list. Prepopulate with world group.
392  */
comex_group_init()393 void comex_group_init()
394 {
395     int status = 0;
396     int i = 0;
397     int smallest_rank_with_same_hostid = 0;
398     int largest_rank_with_same_hostid = 0;
399     int size_node = 0;
400     comex_group_t group = 0;
401     comex_igroup_t *igroup = NULL;
402     long *sorted = NULL;
403     int count = 0;
404 
405     /* populate g_state */
406 
407     /* dup MPI_COMM_WORLD and get group, rank, and size */
408     status = MPI_Comm_dup(MPI_COMM_WORLD, &(g_state.comm));
409     COMEX_ASSERT(MPI_SUCCESS == status);
410     status = MPI_Comm_group(g_state.comm, &(g_state.group));
411     COMEX_ASSERT(MPI_SUCCESS == status);
412     status = MPI_Comm_rank(g_state.comm, &(g_state.rank));
413     COMEX_ASSERT(MPI_SUCCESS == status);
414     status = MPI_Comm_size(g_state.comm, &(g_state.size));
415     COMEX_ASSERT(MPI_SUCCESS == status);
416 
417 #if DEBUG_TO_FILE
418     {
419         char pathname[80];
420         sprintf(pathname, "trace.%d.log", g_state.rank);
421         comex_trace_file = fopen(pathname, "w");
422         COMEX_ASSERT(NULL != comex_trace_file);
423 
424         printf("[%d] comex_group_init()\n", RANK_OR_PID);
425     }
426 #endif
427 
428     /* need to figure out which proc is master on each node */
429     g_state.hostid = (long*)malloc(sizeof(long)*g_state.size);
430     g_state.hostid[g_state.rank] = xgethostid();
431     status = MPI_Allgather(MPI_IN_PLACE, 1, MPI_LONG,
432             g_state.hostid, 1, MPI_LONG, g_state.comm);
433     COMEX_ASSERT(MPI_SUCCESS == status);
434      /* First create a temporary node communicator and then
435       * split further into number of gruoups within the node */
436      MPI_Comm temp_node_comm;
437      int temp_node_size;
438     /* create node comm */
439     /* MPI_Comm_split requires a non-negative color,
440      * so sort and sanitize */
441     sorted = (long*)malloc(sizeof(long) * g_state.size);
442     (void)memcpy(sorted, g_state.hostid, sizeof(long)*g_state.size);
443     qsort(sorted, g_state.size, sizeof(long), cmplong);
444     for (i=0; i<g_state.size-1; ++i) {
445         if (sorted[i] == g_state.hostid[g_state.rank])
446         {
447             break;
448         }
449         if (sorted[i] != sorted[i+1]) {
450             count += 1;
451         }
452     }
453     free(sorted);
454 #if DEBUG
455     printf("count: %d\n", count);
456 #endif
457     status = MPI_Comm_split(MPI_COMM_WORLD, count,
458             g_state.rank, &temp_node_comm);
459     int node_group_size, node_group_rank;
460     MPI_Comm_size(temp_node_comm, &node_group_size);
461     MPI_Comm_rank(temp_node_comm, &node_group_rank);
462     int node_rank0, num_nodes;
463     node_rank0 = (node_group_rank == 0) ? 1 : 0;
464     MPI_Allreduce(&node_rank0, &num_nodes, 1, MPI_INT, MPI_SUM,
465         g_state.comm);
466     smallest_rank_with_same_hostid = g_state.rank;
467     largest_rank_with_same_hostid = g_state.rank;
468     for (i=0; i<g_state.size; ++i) {
469         if (g_state.hostid[i] == g_state.hostid[g_state.rank]) {
470             ++size_node;
471             if (i < smallest_rank_with_same_hostid) {
472                 smallest_rank_with_same_hostid = i;
473             }
474             if (i > largest_rank_with_same_hostid) {
475                 largest_rank_with_same_hostid = i;
476             }
477         }
478     }
479     /* Get nuber of Progress-Ranks per node from environment variable
480      * equal to 1 by default */
481     int num_progress_ranks_per_node = get_num_progress_ranks_per_node();
482     /* Perform check on the number of Progress-Ranks */
483     if (size_node < 2 * num_progress_ranks_per_node) {
484         comex_error("ranks per node, must be at least",
485             2 * num_progress_ranks_per_node);
486     }
487     if (size_node % num_progress_ranks_per_node > 0) {
488         comex_error("number of ranks per node must be multiple of number of process groups per node", -1);
489     }
490     int is_node_ranks_packed = get_progress_rank_distribution_on_node();
491     int split_group_size;
492     split_group_size = node_group_size / num_progress_ranks_per_node;
493      MPI_Comm_free(&temp_node_comm);
494     g_state.master = (int*)malloc(sizeof(int)*g_state.size);
495     g_state.master[g_state.rank] = get_my_master_rank_with_same_hostid(g_state.rank,
496         split_group_size, smallest_rank_with_same_hostid, largest_rank_with_same_hostid,
497         num_progress_ranks_per_node, is_node_ranks_packed);
498 #if DEBUG
499     printf("[%d] rank; split_group_size: %d\n", g_state.rank, split_group_size);
500     printf("[%d] rank; largest_rank_with_same_hostid[%d]; my master is:[%d]\n",
501         g_state.rank, largest_rank_with_same_hostid, g_state.master[g_state.rank]);
502 #endif
503     status = MPI_Allgather(MPI_IN_PLACE, 1, MPI_INT,
504             g_state.master, 1, MPI_INT, g_state.comm);
505     COMEX_ASSERT(MPI_SUCCESS == status);
506 
507     COMEX_ASSERT(group_list == NULL);
508 
509     // put split group stamps
510     int proc_split_group_stamp;
511     int num_split_groups;
512     num_split_groups = num_nodes * num_progress_ranks_per_node;
513     int* split_group_list = (int*)malloc(sizeof(int)*num_split_groups);
514     int split_group_index = 0;
515     int j;
516     for (i=0; i<g_state.size; i++) {
517       for (j=0; j<i; j++) {
518         if (g_state.master[i] == g_state.master[j])
519             break;
520       }
521       if(i == j) {
522         split_group_list[split_group_index] = g_state.master[i];
523         split_group_index++;
524       }
525     }
526     // label each process
527     for (j=0; j<num_split_groups; j++) {
528       if (split_group_list[j] == g_state.master[g_state.rank]) {
529         proc_split_group_stamp = j;
530       }
531     }
532 #if DEBUG
533     printf("proc_split_group_stamp[%ld]: %ld\n",
534        g_state.rank, proc_split_group_stamp);
535 #endif
536     free(split_group_list);
537     /* create a comm of only the workers */
538     if (g_state.master[g_state.rank] == g_state.rank) {
539         /* I'm a master */
540         MPI_Comm delete_me;
541         status = MPI_Comm_split(g_state.comm, 0, g_state.rank, &delete_me);
542         COMEX_ASSERT(MPI_SUCCESS == status);
543         /* masters don't need their own comm */
544         if (MPI_COMM_NULL != delete_me) {
545             MPI_Comm_free(&delete_me);
546         }
547 #if DEBUG
548         printf("Creating comm: I AM MASTER[%ld]\n", g_state.rank);
549 #endif
550     }
551     else {
552         /* I'm a worker */
553         /* create the head of the group linked list */
554         _create_group_and_igroup(&group, &igroup);
555         status = MPI_Comm_split(
556                 g_state.comm, 1, g_state.rank, &(igroup->comm));
557         COMEX_ASSERT(MPI_SUCCESS == status);
558         status = MPI_Comm_group(igroup->comm, &(igroup->group));
559         COMEX_ASSERT(MPI_SUCCESS == status);
560         status = MPI_Comm_rank(igroup->comm, &(igroup->rank));
561         COMEX_ASSERT(MPI_SUCCESS == status);
562         status = MPI_Comm_size(igroup->comm, &(igroup->size));
563         COMEX_ASSERT(MPI_SUCCESS == status);
564         _igroup_set_world_ranks(igroup);
565         COMEX_ASSERT(igroup->world_ranks != NULL);
566 #if DEBUG
567         printf("Creating comm: I AM WORKER[%ld]\n", g_state.rank);
568 #endif
569     }
570     status = MPI_Comm_split(MPI_COMM_WORLD, proc_split_group_stamp,
571             g_state.rank, &(g_state.node_comm));
572     COMEX_ASSERT(MPI_SUCCESS == status);
573     /* node rank */
574     status = MPI_Comm_rank(g_state.node_comm, &(g_state.node_rank));
575     COMEX_ASSERT(MPI_SUCCESS == status);
576     /* node size */
577     status = MPI_Comm_size(g_state.node_comm, &(g_state.node_size));
578     COMEX_ASSERT(MPI_SUCCESS == status);
579 
580 #if DEBUG
581     printf("node_rank[%d]/ size[%d]\n", g_state.node_rank, g_state.node_size);
582     if (g_state.master[g_state.rank] == g_state.rank) {
583         printf("[%d] world %d/%d\tI'm a master\n",
584             RANK_OR_PID, g_state.rank, g_state.size);
585     }
586     else {
587         printf("[%d] world %d/%d\tI'm a worker\n",
588             RANK_OR_PID, g_state.rank, g_state.size);
589     }
590 #endif
591 }
592 
593 
comex_group_finalize()594 void comex_group_finalize()
595 {
596     int status;
597     comex_igroup_t *current_group_list_item = group_list;
598     comex_igroup_t *previous_group_list_item = NULL;
599 
600 #if DEBUG
601     printf("[%d] comex_group_finalize()\n", RANK_OR_PID);
602 #endif
603 
604     while (current_group_list_item != NULL) {
605         previous_group_list_item = current_group_list_item;
606         current_group_list_item = current_group_list_item->next;
607         _igroup_free(previous_group_list_item);
608     }
609 
610     free(g_state.master);
611     free(g_state.hostid);
612     status = MPI_Comm_free(&(g_state.node_comm));
613     COMEX_ASSERT(MPI_SUCCESS == status);
614     status = MPI_Group_free(&(g_state.group));
615     COMEX_ASSERT(MPI_SUCCESS == status);
616     status = MPI_Comm_free(&(g_state.comm));
617     COMEX_ASSERT(MPI_SUCCESS == status);
618 }
619 
620 
xgethostid()621 static long xgethostid()
622 {
623 #if defined(__bgp__)
624 #warning BGP
625     long nodeid;
626     int matched,midplane,nodecard,computecard;
627     char rack_row,rack_col;
628     char location[128];
629     char location_clean[128];
630     (void) memset(location, '\0', 128);
631     (void) memset(location_clean, '\0', 128);
632     _BGP_Personality_t personality;
633     Kernel_GetPersonality(&personality, sizeof(personality));
634     BGP_Personality_getLocationString(&personality, location);
635     matched = sscanf(location, "R%c%c-M%1d-N%2d-J%2d",
636             &rack_row, &rack_col, &midplane, &nodecard, &computecard);
637     assert(matched == 5);
638     sprintf(location_clean, "%2d%02d%1d%02d%02d",
639             (int)rack_row, (int)rack_col, midplane, nodecard, computecard);
640     nodeid = atol(location_clean);
641 #elif defined(__bgq__)
642 #warning BGQ
643     int nodeid;
644     MPIX_Hardware_t hw;
645     MPIX_Hardware(&hw);
646 
647     nodeid = hw.Coords[0] * hw.Size[1] * hw.Size[2] * hw.Size[3] * hw.Size[4]
648         + hw.Coords[1] * hw.Size[2] * hw.Size[3] * hw.Size[4]
649         + hw.Coords[2] * hw.Size[3] * hw.Size[4]
650         + hw.Coords[3] * hw.Size[4]
651         + hw.Coords[4];
652 #elif defined(__CRAYXT) || defined(__CRAYXE)
653 #warning CRAY
654     int nodeid;
655 #  if defined(__CRAYXT)
656     PMI_Portals_get_nid(g_state.rank, &nodeid);
657 #  elif defined(__CRAYXE)
658     PMI_Get_nid(g_state.rank, &nodeid);
659 #  endif
660 #else
661     long nodeid = gethostid();
662 #endif
663 
664     return nodeid;
665 }
666