This source file includes following definitions.
- nice_send
- nice_recv
- nice_barrier
- main
1
2
3
4
5
6
7
8
9
10
11
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <time.h>
17 #include <sys/utsname.h>
18
19 #include <mpi.h>
20
21 #define NCHARS 30
22 const int max_depth = 4;
23
24
25
26
27
28
29
30
31
32
33
34
35 static int nice_send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
36
37 return MPI_Send(buf, count, datatype, dest, tag, comm);
38 }
39
40
41 static int nice_recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) {
42 MPI_Request req;
43 int flag;
44 struct timespec dt;
45
46
47
48
49
50
51
52
53
54 dt.tv_sec = 0;
55 dt.tv_nsec = 100000;
56
57 MPI_Irecv(buf, count, datatype, source, tag, comm, &req);
58
59 MPI_Test(&req, &flag, status);
60 while ( ! flag ) {
61 nanosleep(&dt, NULL);
62 MPI_Test(&req, &flag, status);
63 }
64 return MPI_SUCCESS;
65 }
66
67
68 static void nice_barrier(MPI_Comm comm) {
69 int me, np, jump, buf = -1;
70
71 MPI_Comm_rank(comm,&me);
72 MPI_Comm_size(comm,&np);
73
74
75 for ( jump = 1; jump < np; jump <<= 1 ) {
76 if ( ( me & jump ) != 0 ) {
77 nice_send(&buf, 1, MPI_INT, me - jump, 343, comm);
78 break;
79 } else if ( me + jump < np ) {
80 nice_recv(&buf, 1, MPI_INT, me + jump, 343, comm, MPI_STATUS_IGNORE);
81 }
82 }
83
84
85 if ( 0 != me ) {
86 nice_recv(&buf, 1, MPI_INT, me - jump, 344, comm, MPI_STATUS_IGNORE);
87 }
88 jump >>= 1;
89 for ( ; jump > 0; jump >>= 1 ) {
90 if ( me + jump < np ) {
91 nice_send(&buf, 1, MPI_INT, me + jump, 344, comm);
92 }
93 }
94 }
95
96
97 int main (int argc, char **argv)
98 {
99 char bufs [NCHARS];
100 char bufr[2][NCHARS];
101 MPI_Comm parent;
102 int level = 0, participate = 1;
103 struct utsname buf;
104
105
106 #if defined(OPEN_MPI)
107 if (OMPI_MAJOR_VERSION < 2) {
108 printf("Skipping, because the orte cannot handle concurrent MPI_Comm_spawns\n");
109 return 77;
110 } else {
111 printf("Verify that this test is truly working because conncurrent MPI_Comm_spawns"
112 " has not worked before.\n");
113 }
114 #endif
115
116 uname(&buf);
117 printf("I AM pid %d with level %d on %s\n", getpid(), (argc < 2)?0:atoi(argv[1]), buf.nodename);
118
119 MPI_Init(&argc, &argv);
120 MPI_Comm_get_parent(&parent);
121
122 if (MPI_COMM_NULL != parent) {
123
124 level = atoi(argv[1]);
125 MPI_Recv(&bufr[0], sizeof(char)*NCHARS, MPI_CHAR, MPI_ANY_SOURCE,
126 MPI_ANY_TAG, parent, MPI_STATUS_IGNORE);
127 printf("Parent sent: %s\n", bufr[0]);
128 } else {
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 int me, np;
144
145 MPI_Comm_size(MPI_COMM_WORLD,&np);
146 MPI_Comm_rank(MPI_COMM_WORLD,&me);
147
148 if ( np > 4 ) {
149
150 if ( ( me & 3 ) != 0 ) participate = 0;
151 } else
152 if ( np > 2 ) {
153
154 if ( ( me & 1 ) != 0 ) participate = 0;
155 }
156 }
157
158
159 if ( participate ) {
160 printf("level = %d\n", level);
161
162
163 sprintf(bufs,"level %d (pid:%d)", level, getpid());
164
165
166 if (level < max_depth) {
167 int i, nspawn = 2, errcodes[1];
168 MPI_Request req[2];
169 MPI_Comm comm[2];
170 char argv1[NCHARS];
171 char *args[2];
172
173
174 if ( level == 0 ) nspawn = 1;
175
176
177 snprintf(argv1, sizeof(argv1), "%d", level+1);
178 args[0] = argv1;
179 args[1] = NULL;
180
181
182 for ( i = 0; i < nspawn; i++ ) {
183 MPI_Comm_spawn(argv[0], args, 1, MPI_INFO_NULL, 0, MPI_COMM_SELF,
184 &comm[i], errcodes);
185 MPI_Send(&bufs, sizeof(char)*NCHARS, MPI_CHAR, 0, 100, comm[i]);
186 MPI_Irecv(&bufr[i], sizeof(char)*NCHARS, MPI_CHAR, MPI_ANY_SOURCE,
187 MPI_ANY_TAG, comm[i], &req[i]);
188 }
189
190
191 MPI_Waitall(nspawn, req, MPI_STATUSES_IGNORE);
192 for ( i = 0; i < nspawn; i++ )
193 printf("Child %d sent: %s\n", i, bufr[i]);
194 }
195
196
197 if (MPI_COMM_NULL != parent) {
198 MPI_Send(&bufs, sizeof(char)*NCHARS, MPI_CHAR, 0, 100, parent);
199 }
200 }
201
202
203
204 if (MPI_COMM_NULL == parent) {
205 nice_barrier(MPI_COMM_WORLD);
206 }
207
208 MPI_Finalize();
209 return 0;
210 }