This source file includes following definitions.
- NBC_Allgather_args_compare
- nbc_allgather_init
- ompi_coll_libnbc_iallgather
- nbc_allgather_inter_init
- ompi_coll_libnbc_iallgather_inter
- allgather_sched_linear
- allgather_sched_recursivedoubling
- ompi_coll_libnbc_allgather_init
- ompi_coll_libnbc_allgather_inter_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "nbc_internal.h"
22
23 static inline int allgather_sched_linear(
24 int rank, int comm_size, NBC_Schedule *schedule, const void *sendbuf,
25 int scount, struct ompi_datatype_t *sdtype, void *recvbuf, int rcount,
26 struct ompi_datatype_t *rdtype);
27 static inline int allgather_sched_recursivedoubling(
28 int rank, int comm_size, NBC_Schedule *schedule, const void *sbuf,
29 int scount, struct ompi_datatype_t *sdtype, void *rbuf, int rcount,
30 struct ompi_datatype_t *rdtype);
31
32 #ifdef NBC_CACHE_SCHEDULE
33
34 int NBC_Allgather_args_compare(NBC_Allgather_args *a, NBC_Allgather_args *b, void *param) {
35 if ((a->sendbuf == b->sendbuf) &&
36 (a->sendcount == b->sendcount) &&
37 (a->sendtype == b->sendtype) &&
38 (a->recvbuf == b->recvbuf) &&
39 (a->recvcount == b->recvcount) &&
40 (a->recvtype == b->recvtype) ) {
41 return 0;
42 }
43
44 if( a->sendbuf < b->sendbuf ) {
45 return -1;
46 }
47
48 return 1;
49 }
50 #endif
51
52 static int nbc_allgather_init(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
53 MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
54 struct mca_coll_base_module_2_3_0_t *module, bool persistent)
55 {
56 int rank, p, res;
57 MPI_Aint rcvext;
58 NBC_Schedule *schedule;
59 char *rbuf, inplace;
60 #ifdef NBC_CACHE_SCHEDULE
61 NBC_Allgather_args *args, *found, search;
62 #endif
63 enum { NBC_ALLGATHER_LINEAR, NBC_ALLGATHER_RDBL} alg;
64 ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
65
66 NBC_IN_PLACE(sendbuf, recvbuf, inplace);
67
68 rank = ompi_comm_rank (comm);
69 p = ompi_comm_size (comm);
70 int is_commsize_pow2 = !(p & (p - 1));
71
72 if (libnbc_iallgather_algorithm == 0) {
73 alg = NBC_ALLGATHER_LINEAR;
74 } else {
75
76 if (libnbc_iallgather_algorithm == 1) {
77 alg = NBC_ALLGATHER_LINEAR;
78 } else if (libnbc_iallgather_algorithm == 2 && is_commsize_pow2) {
79 alg = NBC_ALLGATHER_RDBL;
80 } else {
81 alg = NBC_ALLGATHER_LINEAR;
82 }
83 }
84
85 res = ompi_datatype_type_extent(recvtype, &rcvext);
86 if (MPI_SUCCESS != res) {
87 return res;
88 }
89
90 if (inplace) {
91 sendtype = recvtype;
92 sendcount = recvcount;
93 } else if (!persistent) {
94
95 rbuf = (char *) recvbuf + rank * recvcount * rcvext;
96 res = NBC_Copy (sendbuf, sendcount, sendtype, rbuf, recvcount, recvtype, comm);
97 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
98 return res;
99 }
100 }
101 if (1 == p && (!persistent || inplace)) {
102 return nbc_get_noop_request(persistent, request);
103 }
104
105 #ifdef NBC_CACHE_SCHEDULE
106
107 search.sendbuf = sendbuf;
108 search.sendcount = sendcount;
109 search.sendtype = sendtype;
110 search.recvbuf = recvbuf;
111 search.recvcount = recvcount;
112 search.recvtype = recvtype;
113 found = (NBC_Allgather_args *) hb_tree_search ((hb_tree*)libnbc_module->NBC_Dict[NBC_ALLGATHER], &search);
114 if (NULL == found) {
115 #endif
116 schedule = OBJ_NEW(NBC_Schedule);
117 if (OPAL_UNLIKELY(NULL == schedule)) {
118 return OMPI_ERR_OUT_OF_RESOURCE;
119 }
120
121 if (persistent && !inplace) {
122
123
124 rbuf = (char *)recvbuf + rank * recvcount * rcvext;
125 res = NBC_Sched_copy((void *)sendbuf, false, sendcount, sendtype,
126 rbuf, false, recvcount, recvtype, schedule, true);
127 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
128 OBJ_RELEASE(schedule);
129 return res;
130 }
131 }
132
133 switch (alg) {
134 case NBC_ALLGATHER_LINEAR:
135 res = allgather_sched_linear(rank, p, schedule, sendbuf, sendcount, sendtype,
136 recvbuf, recvcount, recvtype);
137 break;
138 case NBC_ALLGATHER_RDBL:
139 res = allgather_sched_recursivedoubling(rank, p, schedule, sendbuf, sendcount,
140 sendtype, recvbuf, recvcount, recvtype);
141 break;
142 }
143
144 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
145 OBJ_RELEASE(schedule);
146 return res;
147 }
148
149 res = NBC_Sched_commit(schedule);
150 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
151 OBJ_RELEASE(schedule);
152 return res;
153 }
154
155 #ifdef NBC_CACHE_SCHEDULE
156
157 args = (NBC_Allgather_args *) malloc (sizeof (args));
158 args->sendbuf = sendbuf;
159 args->sendcount = sendcount;
160 args->sendtype = sendtype;
161 args->recvbuf = recvbuf;
162 args->recvcount = recvcount;
163 args->recvtype = recvtype;
164 args->schedule = schedule;
165
166 res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLGATHER], args, args, 0);
167 if (res != 0) {
168 free (args);
169 } else {
170 OBJ_RETAIN(schedule);
171 }
172
173
174 if (++libnbc_module->NBC_Dict_size[NBC_ALLGATHER] > NBC_SCHED_DICT_UPPER) {
175 NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLGATHER], &libnbc_module->NBC_Dict_size[NBC_ALLGATHER]);
176 }
177 } else {
178
179 schedule = found->schedule;
180 OBJ_RETAIN(schedule);
181 }
182 #endif
183
184 res = NBC_Schedule_request(schedule, comm, libnbc_module, persistent, request, NULL);
185 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
186 OBJ_RELEASE(schedule);
187 return res;
188 }
189
190 return OMPI_SUCCESS;
191 }
192
193 int ompi_coll_libnbc_iallgather(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
194 MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
195 struct mca_coll_base_module_2_3_0_t *module)
196 {
197 int res = nbc_allgather_init(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
198 comm, request, module, false);
199 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
200 return res;
201 }
202
203 res = NBC_Start(*(ompi_coll_libnbc_request_t **)request);
204 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
205 NBC_Return_handle (*(ompi_coll_libnbc_request_t **)request);
206 *request = &ompi_request_null.request;
207 return res;
208 }
209
210 return OMPI_SUCCESS;
211 }
212
213 static int nbc_allgather_inter_init(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
214 MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
215 struct mca_coll_base_module_2_3_0_t *module, bool persistent)
216 {
217 int res, rsize;
218 MPI_Aint rcvext;
219 NBC_Schedule *schedule;
220 char *rbuf;
221 ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
222
223 res = ompi_datatype_type_extent(recvtype, &rcvext);
224 if (MPI_SUCCESS != res) {
225 NBC_Error ("MPI Error in ompi_datatype_type_extent() (%i)", res);
226 return res;
227 }
228
229 rsize = ompi_comm_remote_size (comm);
230
231
232 schedule = OBJ_NEW(NBC_Schedule);
233 if (OPAL_UNLIKELY(NULL == schedule)) {
234 return OMPI_ERR_OUT_OF_RESOURCE;
235 }
236
237
238 for (int r = 0 ; r < rsize ; ++r) {
239
240 rbuf = (char *) recvbuf + r * recvcount * rcvext;
241 res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, r, schedule, false);
242 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
243 OBJ_RELEASE(schedule);
244 return res;
245 }
246
247
248 res = NBC_Sched_send (sendbuf, false, sendcount, sendtype, r, schedule, false);
249 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
250 OBJ_RELEASE(schedule);
251 return res;
252 }
253 }
254
255 res = NBC_Sched_commit (schedule);
256 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
257 OBJ_RELEASE(schedule);
258 return res;
259 }
260
261 res = NBC_Schedule_request(schedule, comm, libnbc_module, persistent, request, NULL);
262 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
263 OBJ_RELEASE(schedule);
264 return res;
265 }
266
267 return OMPI_SUCCESS;
268 }
269
270 int ompi_coll_libnbc_iallgather_inter(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
271 MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
272 struct mca_coll_base_module_2_3_0_t *module) {
273 int res = nbc_allgather_inter_init(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
274 comm, request, module, false);
275 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
276 return res;
277 }
278
279 res = NBC_Start(*(ompi_coll_libnbc_request_t **)request);
280 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
281 NBC_Return_handle (*(ompi_coll_libnbc_request_t **)request);
282 *request = &ompi_request_null.request;
283 return res;
284 }
285
286 return OMPI_SUCCESS;
287 }
288
289
290
291
292
293
294
295
296
297 static inline int allgather_sched_linear(
298 int rank, int comm_size, NBC_Schedule *schedule, const void *sendbuf,
299 int scount, struct ompi_datatype_t *sdtype, void *recvbuf, int rcount,
300 struct ompi_datatype_t *rdtype)
301 {
302 int res = OMPI_SUCCESS;
303 ptrdiff_t rlb, rext;
304
305 res = ompi_datatype_get_extent(rdtype, &rlb, &rext);
306 char *sbuf = (char *)recvbuf + rank * rcount * rext;
307
308 for (int remote = 0; remote < comm_size ; ++remote) {
309 if (remote != rank) {
310
311 char *rbuf = (char *)recvbuf + remote * rcount * rext;
312 res = NBC_Sched_recv(rbuf, false, rcount, rdtype, remote, schedule, false);
313 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) { goto cleanup_and_return; }
314
315
316 res = NBC_Sched_send(sbuf, false, rcount, rdtype, remote, schedule, false);
317 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) { goto cleanup_and_return; }
318 }
319 }
320
321 cleanup_and_return:
322 return res;
323 }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355 static inline int allgather_sched_recursivedoubling(
356 int rank, int comm_size, NBC_Schedule *schedule, const void *sbuf,
357 int scount, struct ompi_datatype_t *sdtype, void *rbuf, int rcount,
358 struct ompi_datatype_t *rdtype)
359 {
360 int res = OMPI_SUCCESS;
361 ptrdiff_t rlb, rext;
362 char *tmpsend = NULL, *tmprecv = NULL;
363
364 res = ompi_datatype_get_extent(rdtype, &rlb, &rext);
365 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) { goto cleanup_and_return; }
366
367 int sendblocklocation = rank;
368 for (int distance = 1; distance < comm_size; distance <<= 1) {
369 int remote = rank ^ distance;
370
371 tmpsend = (char *)rbuf + (ptrdiff_t)sendblocklocation * (ptrdiff_t)rcount * rext;
372 if (rank < remote) {
373 tmprecv = (char *)rbuf + (ptrdiff_t)(sendblocklocation + distance) * (ptrdiff_t)rcount * rext;
374 } else {
375 tmprecv = (char *)rbuf + (ptrdiff_t)(sendblocklocation - distance) * (ptrdiff_t)rcount * rext;
376 sendblocklocation -= distance;
377 }
378
379 res = NBC_Sched_send(tmpsend, false, (ptrdiff_t)distance * (ptrdiff_t)rcount,
380 rdtype, remote, schedule, false);
381 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) { goto cleanup_and_return; }
382
383 res = NBC_Sched_recv(tmprecv, false, (ptrdiff_t)distance * (ptrdiff_t)rcount,
384 rdtype, remote, schedule, true);
385 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) { goto cleanup_and_return; }
386 }
387
388 cleanup_and_return:
389 return res;
390 }
391
392 int ompi_coll_libnbc_allgather_init(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
393 MPI_Datatype recvtype, struct ompi_communicator_t *comm, MPI_Info info, ompi_request_t ** request,
394 struct mca_coll_base_module_2_3_0_t *module) {
395 int res = nbc_allgather_init(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
396 comm, request, module, true);
397 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
398 return res;
399 }
400
401 return OMPI_SUCCESS;
402 }
403
404 int ompi_coll_libnbc_allgather_inter_init(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
405 MPI_Datatype recvtype, struct ompi_communicator_t *comm, MPI_Info info, ompi_request_t ** request,
406 struct mca_coll_base_module_2_3_0_t *module) {
407 int res = nbc_allgather_inter_init(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype,
408 comm, request, module, true);
409 if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
410 return res;
411 }
412
413 return OMPI_SUCCESS;
414 }