1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 /** PGROUP Creation (Intercommunicator Method)
7   * James Dinan <dinan@mcs.anl.gov>
8   * May, 2011
9   *
10   * In this test, processes create an intracommunicator and creation is
11   * collective only on the members of the new communicator, not on the parent
12   * communicator.  This is accomplished by building up and merging
13   * intercommunicators starting with MPI_COMM_SELF for each process involved.
14   */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <assert.h>
19 
20 #include <mpi.h>
21 #include "mpitest.h"
22 
23 #define INTERCOMM_TAG 0
24 
25 const int verbose = 0;
26 
27 void pgroup_create(int grp_size, int *pid_list, MPI_Comm * group_out);
28 void pgroup_free(MPI_Comm * group);
29 
30 /** Free the group
31   */
pgroup_free(MPI_Comm * group)32 void pgroup_free(MPI_Comm * group)
33 {
34     /* Note: It's ok to compare predefined handles */
35     if (*group == MPI_COMM_NULL || *group == MPI_COMM_SELF)
36         return;
37 
38     MPI_Comm_free((MPI_Comm *) group);
39 }
40 
41 
42 /* Create a processor group containing the processes in pid_list.
43  *
44  * NOTE: pid_list list must be identical and sorted on all processes
45  */
pgroup_create(int grp_size,int * pid_list,MPI_Comm * group_out)46 void pgroup_create(int grp_size, int *pid_list, MPI_Comm * group_out)
47 {
48     int i, grp_me, me, nproc, merge_size;
49     MPI_Comm pgroup, inter_pgroup;
50 
51     MPI_Comm_rank(MPI_COMM_WORLD, &me);
52     MPI_Comm_size(MPI_COMM_WORLD, &nproc);
53 
54     /* CASE: Group size 0 */
55     if (grp_size == 0) {
56         *group_out = MPI_COMM_NULL;
57         return;
58     }
59 
60     /* CASE: Group size 1 */
61     else if (grp_size == 1 && pid_list[0] == me) {
62         *group_out = MPI_COMM_SELF;
63         return;
64     }
65 
66     /* CHECK: If I'm not a member, return COMM_NULL */
67     grp_me = -1;
68     for (i = 0; i < grp_size; i++) {
69         if (pid_list[i] == me) {
70             grp_me = i;
71             break;
72         }
73     }
74 
75     if (grp_me < 0) {
76         *group_out = MPI_COMM_NULL;
77         return;
78     }
79 
80     pgroup = MPI_COMM_SELF;
81 
82     for (merge_size = 1; merge_size < grp_size; merge_size *= 2) {
83         int gid = grp_me / merge_size;
84         MPI_Comm pgroup_old = pgroup;
85 
86         if (gid % 2 == 0) {
87             /* Check if right partner doesn't exist */
88             if ((gid + 1) * merge_size >= grp_size)
89                 continue;
90 
91             MPI_Intercomm_create(pgroup, 0, MPI_COMM_WORLD, pid_list[(gid + 1) * merge_size],
92                                  INTERCOMM_TAG, &inter_pgroup);
93             MPI_Intercomm_merge(inter_pgroup, 0 /* LOW */ , &pgroup);
94         } else {
95             MPI_Intercomm_create(pgroup, 0, MPI_COMM_WORLD, pid_list[(gid - 1) * merge_size],
96                                  INTERCOMM_TAG, &inter_pgroup);
97             MPI_Intercomm_merge(inter_pgroup, 1 /* HIGH */ , &pgroup);
98         }
99 
100         MPI_Comm_free(&inter_pgroup);
101         if (pgroup_old != MPI_COMM_SELF)
102             MPI_Comm_free(&pgroup_old);
103     }
104 
105     *group_out = pgroup;
106 }
107 
108 
main(int argc,char ** argv)109 int main(int argc, char **argv)
110 {
111     int me, nproc, i;
112     int gsize, *glist;
113     MPI_Comm group;
114 
115     MTest_Init(&argc, &argv);
116 
117     MPI_Comm_rank(MPI_COMM_WORLD, &me);
118     MPI_Comm_size(MPI_COMM_WORLD, &nproc);
119 
120     gsize = nproc / 2 + (nproc % 2);
121     glist = malloc(gsize * sizeof(int));
122 
123     for (i = 0; i < nproc; i += 2)
124         glist[i / 2] = i;
125 
126     MPI_Barrier(MPI_COMM_WORLD);
127 
128     if (me % 2 == 0) {
129         int gme, gnproc;
130         double t1, t2;
131 
132         t1 = MPI_Wtime();
133         pgroup_create(gsize, glist, &group);
134         t2 = MPI_Wtime();
135 
136         MPI_Barrier(group);
137 
138         MPI_Comm_rank(group, &gme);
139         MPI_Comm_size(group, &gnproc);
140         if (verbose)
141             printf("[%d] Group rank = %d, size = %d time = %f sec\n", me, gme, gnproc, t2 - t1);
142 
143         pgroup_free(&group);
144     }
145 
146     free(glist);
147 
148     MTest_Finalize(0);
149     return MTestReturnValue(0);
150 }
151