13
#include "comex_impl.h"
16
/* COMEX has the notion of a default group and a world group. */
17
comex_group_t COMEX_Default_Proc_Group = 0;
18
comex_group_t COMEX_World_Proc_Group = 0;
20
/* the HEAD of the group linked list */
21
comex_igroup_t *group_list = NULL;
25
* Return the comex_igroup_t instance given the comex_group_t.
27
* The group linked list is searched sequentially until the given group
28
* is found. It is an error if this function is called before
29
* comex_group_init(). An error occurs if the given group is not found.
31
comex_igroup_t* comex_get_igroup_from_group(comex_group_t id)
33
comex_igroup_t *current_group_list_item = group_list;
35
assert(group_list != NULL);
36
while (current_group_list_item != NULL) {
37
if (current_group_list_item->id == id) {
38
return current_group_list_item;
40
current_group_list_item = current_group_list_item->next;
42
comex_error("comex_group_t lookup failed", -1);
49
* Creates and associates an comex_group_t with an comex_igroup_t.
51
* This does *not* initialize the members of the comex_igroup_t.
53
static void comex_create_group_and_igroup(
54
comex_group_t *id, comex_igroup_t **igroup)
56
comex_igroup_t *new_group_list_item = NULL;
57
comex_igroup_t *last_group_list_item = NULL;
59
/* find the last group in the group linked list */
60
last_group_list_item = group_list;
61
while (last_group_list_item->next != NULL) {
62
last_group_list_item = last_group_list_item->next;
65
/* create, init, and insert the new node for the linked list */
66
new_group_list_item = malloc(sizeof(comex_igroup_t));
67
new_group_list_item->id = last_group_list_item->id + 1;
68
new_group_list_item->next = NULL;
69
last_group_list_item->next = new_group_list_item;
71
/* return the group id and comex_igroup_t */
72
*igroup = new_group_list_item;
73
*id = new_group_list_item->id;
78
* Returns the rank of this process within the given group.
80
int comex_group_rank(comex_group_t id, int *rank)
84
comex_igroup_t *igroup = comex_get_igroup_from_group(id);
85
status = MPI_Group_rank(igroup->group, rank);
86
if (status != MPI_SUCCESS) {
87
comex_error("MPI_Group_rank: Failed ", status);
95
* Returns the size of a group.
97
int comex_group_size(comex_group_t id, int *size)
101
comex_igroup_t *igroup = comex_get_igroup_from_group(id);
102
status = MPI_Group_size(igroup->group, size);
103
if (status != MPI_SUCCESS) {
104
comex_error("MPI_Group_size: Failed ", status);
107
return COMEX_SUCCESS;
111
int comex_group_comm(comex_group_t group, MPI_Comm *comm)
113
comex_igroup_t *igroup = comex_get_igroup_from_group(group);
114
*comm = igroup->comm;
116
return COMEX_SUCCESS;
121
* Translates the given rank from the given group into that of the world group.
123
int comex_group_translate_world(comex_group_t id, int group_rank, int *world_rank)
126
MPI_Group world_group;
127
comex_igroup_t *igroup = comex_get_igroup_from_group(id);
129
status = MPI_Comm_group(l_state.world_comm, &world_group);
130
if (status != MPI_SUCCESS) {
131
comex_error("MPI_Comm_group: Failed ", status);
133
status = MPI_Group_translate_ranks(
134
igroup->group, 1, &group_rank, world_group, world_rank);
135
if (status != MPI_SUCCESS) {
136
comex_error("MPI_Group_translate_ranks: Failed ", status);
139
return COMEX_SUCCESS;
144
* Sets the default comex_group_t.
146
void comex_group_set_default(comex_group_t id)
148
/* sanity check that the group is valid */
149
comex_igroup_t *igroup = comex_get_igroup_from_group(id);
150
assert(NULL != igroup);
151
COMEX_Default_Proc_Group = id;
156
* Gets the default comex_group_t.
158
void comex_group_get_default(comex_group_t *group_out)
160
*group_out = COMEX_Default_Proc_Group;
165
* Gets the world comex_group_t.
167
void comex_group_get_world(comex_group_t *group_out)
169
*group_out = COMEX_World_Proc_Group;
174
* Destroys the given comex_igroup_t.
176
static void comex_igroup_finalize(comex_igroup_t *igroup)
182
status = MPI_Group_free(&igroup->group);
183
if (status != MPI_SUCCESS) {
184
comex_error("MPI_Group_free: Failed ", status);
187
if (igroup->comm != MPI_COMM_NULL) {
188
status = MPI_Comm_free(&igroup->comm);
189
if (status != MPI_SUCCESS) {
190
comex_error("MPI_Comm_free: Failed ", status);
197
* Removes and destroys the given comex_group_t from the group linked list.
199
int comex_group_free(comex_group_t id)
201
comex_igroup_t *current_group_list_item = group_list;
202
comex_igroup_t *previous_group_list_item = NULL;
204
/* find the group to free */
205
while (current_group_list_item != NULL) {
206
if (current_group_list_item->id == id) {
209
previous_group_list_item = current_group_list_item;
210
current_group_list_item = current_group_list_item->next;
212
/* make sure we found a group */
213
assert(current_group_list_item != NULL);
214
/* remove the group from the linked list */
215
if (previous_group_list_item != NULL) {
216
previous_group_list_item->next = current_group_list_item->next;
219
comex_igroup_finalize(current_group_list_item);
220
free(current_group_list_item);
222
return COMEX_SUCCESS;
227
* Create a child group for to the given group.
229
* @param[in] n #procs in this group (<= that in group_parent)
230
* @param[in] pid_list The list of proc ids (w.r.t. group_parent)
231
* @param[out] id_child Handle to store the created group
232
* @param[in] id_parent Parent group
234
int comex_group_create(
235
int n, int *pid_list, comex_group_t id_parent, comex_group_t *id_child)
239
comex_igroup_t *igroup_child = NULL;
240
MPI_Group *group_child = NULL;
241
MPI_Comm *comm_child = NULL;
242
comex_igroup_t *igroup_parent = NULL;
243
MPI_Group *group_parent = NULL;
244
MPI_Comm *comm_parent = NULL;
246
/* create the node in the linked list of groups and */
247
/* get the child's MPI_Group and MPI_Comm, to be populated shortly */
248
comex_create_group_and_igroup(id_child, &igroup_child);
249
group_child = &(igroup_child->group);
250
comm_child = &(igroup_child->comm);
252
/* get the parent's MPI_Group and MPI_Comm */
253
igroup_parent = comex_get_igroup_from_group(id_parent);
254
group_parent = &(igroup_parent->group);
255
comm_parent = &(igroup_parent->comm);
257
status = MPI_Group_incl(*group_parent, n, pid_list, group_child);
258
if (status != MPI_SUCCESS) {
259
comex_error("MPI_Group_incl: Failed ", status);
263
MPI_Comm comm, comm1, comm2;
264
int lvl=1, local_ldr_pos;
265
MPI_Group_rank(*group_child, &grp_me);
266
if (grp_me == MPI_UNDEFINED) {
267
*comm_child = MPI_COMM_NULL;
268
/* FIXME: keeping the group around for now */
269
return COMEX_SUCCESS;
271
/* SK: sanity check for the following bitwise operations */
273
MPI_Comm_dup(MPI_COMM_SELF, &comm); /* FIXME: can be optimized away */
274
local_ldr_pos = grp_me;
277
int remote_ldr_pos = local_ldr_pos^lvl;
278
if (remote_ldr_pos < n) {
279
int remote_leader = pid_list[remote_ldr_pos];
280
MPI_Comm peer_comm = *comm_parent;
281
int high = (local_ldr_pos<remote_ldr_pos)?0:1;
282
MPI_Intercomm_create(
283
comm, 0, peer_comm, remote_leader, tag, &comm1);
284
MPI_Comm_free(&comm);
285
MPI_Intercomm_merge(comm1, high, &comm2);
286
MPI_Comm_free(&comm1);
289
local_ldr_pos &= ((~0)^lvl);
293
/* cleanup temporary group (from MPI_Group_incl above) */
294
MPI_Group_free(group_child);
295
/* get the actual group associated with comm */
296
MPI_Comm_group(*comm_child, group_child);
299
return COMEX_SUCCESS;
304
* Initialize group linked list. Prepopulate with world group.
306
void comex_group_init()
308
/* Initially, World group is the default group */
309
COMEX_World_Proc_Group = 0;
310
COMEX_Default_Proc_Group = 0;
312
/* create the head of the group linked list */
313
assert(group_list == NULL);
314
group_list = malloc(sizeof(comex_igroup_t));
315
group_list->id = COMEX_World_Proc_Group;
316
group_list->next = NULL;
318
/* save MPI world group and communicatior in COMEX_World_Proc_Group */
319
group_list->comm = l_state.world_comm;
320
MPI_Comm_group(l_state.world_comm, &(group_list->group));
324
void comex_group_finalize()
326
comex_igroup_t *current_group_list_item = group_list;
327
comex_igroup_t *previous_group_list_item = NULL;
329
/* don't free the world group (the list head) */
330
current_group_list_item = current_group_list_item->next;
332
while (current_group_list_item != NULL) {
333
previous_group_list_item = current_group_list_item;
334
current_group_list_item = current_group_list_item->next;
335
comex_igroup_finalize(previous_group_list_item);
336
free(previous_group_list_item);