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