Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
2809babd76e8a2c47f03b000be59018380dc022a
[simgrid.git] / src / smpi / colls / smpi_openmpi_selector.cpp
1 /* selector for collective algorithms based on openmpi's default coll_tuned_decision_fixed selector
2  * Updated 02/2022                                                          */
3
4 /* Copyright (c) 2009-2022. The SimGrid Team.
5  * All rights reserved.                                                     */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "colls_private.hpp"
11
12 #include <memory>
13
14 /* FIXME
15 add algos:
16 allreduce nonoverlapping, basic linear
17 alltoall linear_sync
18 bcast chain
19 reduce_scatter butterfly
20 scatter linear_nb
21 */
22
23 namespace simgrid {
24 namespace smpi {
25
26 int allreduce__ompi(const void *sbuf, void *rbuf, int count,
27                     MPI_Datatype dtype, MPI_Op op, MPI_Comm comm)
28 {
29     size_t total_dsize = dtype->size() * (ptrdiff_t)count;
30     int communicator_size = comm->size();
31     int alg = 1;
32     int(*funcs[]) (const void*, void*, int, MPI_Datatype, MPI_Op, MPI_Comm)={
33         &allreduce__lr,
34         &allreduce__lr,
35         &allreduce__rdb,
36         &allreduce__lr,
37         &allreduce__ompi_ring_segmented,
38         &allreduce__rab_rdb
39     };
40
41     /** Algorithms:
42      *  {1, "basic_linear"},
43      *  {2, "nonoverlapping"},
44      *  {3, "recursive_doubling"},
45      *  {4, "ring"},
46      *  {5, "segmented_ring"},
47      *  {6, "rabenseifner"
48      *
49      * Currently, ring, segmented ring, and rabenseifner do not support
50      * non-commutative operations.
51      */
52     if ((op != MPI_OP_NULL) && not op->is_commutative()) {
53         if (communicator_size < 4) {
54             if (total_dsize < 131072) {
55                 alg = 3;
56             } else {
57                 alg = 1;
58             }
59         } else if (communicator_size < 8) {
60             alg = 3;
61         } else if (communicator_size < 16) {
62             if (total_dsize < 1048576) {
63                 alg = 3;
64             } else {
65                 alg = 2;
66             }
67         } else if (communicator_size < 128) {
68             alg = 3;
69         } else if (communicator_size < 256) {
70             if (total_dsize < 131072) {
71                 alg = 2;
72             } else if (total_dsize < 524288) {
73                 alg = 3;
74             } else {
75                 alg = 2;
76             }
77         } else if (communicator_size < 512) {
78             if (total_dsize < 4096) {
79                 alg = 2;
80             } else if (total_dsize < 524288) {
81                 alg = 3;
82             } else {
83                 alg = 2;
84             }
85         } else {
86             if (total_dsize < 2048) {
87                 alg = 2;
88             } else {
89                 alg = 3;
90             }
91         }
92     } else {
93         if (communicator_size < 4) {
94             if (total_dsize < 8) {
95                 alg = 4;
96             } else if (total_dsize < 4096) {
97                 alg = 3;
98             } else if (total_dsize < 8192) {
99                 alg = 4;
100             } else if (total_dsize < 16384) {
101                 alg = 3;
102             } else if (total_dsize < 65536) {
103                 alg = 4;
104             } else if (total_dsize < 262144) {
105                 alg = 5;
106             } else {
107                 alg = 6;
108             }
109         } else if (communicator_size < 8) {
110             if (total_dsize < 16) {
111                 alg = 4;
112             } else if (total_dsize < 8192) {
113                 alg = 3;
114             } else {
115                 alg = 6;
116             }
117         } else if (communicator_size < 16) {
118             if (total_dsize < 8192) {
119                 alg = 3;
120             } else {
121                 alg = 6;
122             }
123         } else if (communicator_size < 32) {
124             if (total_dsize < 64) {
125                 alg = 5;
126             } else if (total_dsize < 4096) {
127                 alg = 3;
128             } else {
129                 alg = 6;
130             }
131         } else if (communicator_size < 64) {
132             if (total_dsize < 128) {
133                 alg = 5;
134             } else {
135                 alg = 6;
136             }
137         } else if (communicator_size < 128) {
138             if (total_dsize < 262144) {
139                 alg = 3;
140             } else {
141                 alg = 6;
142             }
143         } else if (communicator_size < 256) {
144             if (total_dsize < 131072) {
145                 alg = 2;
146             } else if (total_dsize < 262144) {
147                 alg = 3;
148             } else {
149                 alg = 6;
150             }
151         } else if (communicator_size < 512) {
152             if (total_dsize < 4096) {
153                 alg = 2;
154             } else {
155                 alg = 6;
156             }
157         } else if (communicator_size < 2048) {
158             if (total_dsize < 2048) {
159                 alg = 2;
160             } else if (total_dsize < 16384) {
161                 alg = 3;
162             } else {
163                 alg = 6;
164             }
165         } else if (communicator_size < 4096) {
166             if (total_dsize < 2048) {
167                 alg = 2;
168             } else if (total_dsize < 4096) {
169                 alg = 5;
170             } else if (total_dsize < 16384) {
171                 alg = 3;
172             } else {
173                 alg = 6;
174             }
175         } else {
176             if (total_dsize < 2048) {
177                 alg = 2;
178             } else if (total_dsize < 16384) {
179                 alg = 5;
180             } else if (total_dsize < 32768) {
181                 alg = 3;
182             } else {
183                 alg = 6;
184             }
185         }
186     }
187     return funcs[alg-1](sbuf, rbuf, count, dtype, op, comm);
188 }
189
190
191
192 int alltoall__ompi(const void *sbuf, int scount,
193                    MPI_Datatype sdtype,
194                    void* rbuf, int rcount,
195                    MPI_Datatype rdtype,
196                    MPI_Comm comm)
197 {
198     int alg = 1;
199     size_t dsize, total_dsize;
200     int communicator_size = comm->size();
201
202     if (MPI_IN_PLACE != sbuf) {
203         dsize = sdtype->size();
204     } else {
205         dsize = rdtype->size();
206     }
207     total_dsize = dsize * (ptrdiff_t)scount;
208     int (*funcs[])(const void *, int, MPI_Datatype, void*, int, MPI_Datatype, MPI_Comm) = {
209         &alltoall__basic_linear,
210         &alltoall__pair,
211         &alltoall__bruck,
212         &alltoall__basic_linear,
213         &alltoall__basic_linear
214     };
215     /** Algorithms:
216      *  {1, "linear"},
217      *  {2, "pairwise"},
218      *  {3, "modified_bruck"},
219      *  {4, "linear_sync"},
220      *  {5, "two_proc"},
221      */
222     if (communicator_size == 2) {
223         if (total_dsize < 2) {
224             alg = 2;
225         } else if (total_dsize < 4) {
226             alg = 5;
227         } else if (total_dsize < 16) {
228             alg = 2;
229         } else if (total_dsize < 64) {
230             alg = 5;
231         } else if (total_dsize < 256) {
232             alg = 2;
233         } else if (total_dsize < 4096) {
234             alg = 5;
235         } else if (total_dsize < 32768) {
236             alg = 2;
237         } else if (total_dsize < 262144) {
238             alg = 4;
239         } else if (total_dsize < 1048576) {
240             alg = 5;
241         } else {
242             alg = 2;
243         }
244     } else if (communicator_size < 8) {
245         if (total_dsize < 8192) {
246             alg = 4;
247         } else if (total_dsize < 16384) {
248             alg = 1;
249         } else if (total_dsize < 65536) {
250             alg = 4;
251         } else if (total_dsize < 524288) {
252             alg = 1;
253         } else if (total_dsize < 1048576) {
254             alg = 2;
255         } else {
256             alg = 1;
257         }
258     } else if (communicator_size < 16) {
259         if (total_dsize < 262144) {
260             alg = 4;
261         } else {
262             alg = 1;
263         }
264     } else if (communicator_size < 32) {
265         if (total_dsize < 4) {
266             alg = 4;
267         } else if (total_dsize < 512) {
268             alg = 3;
269         } else if (total_dsize < 8192) {
270             alg = 4;
271         } else if (total_dsize < 32768) {
272             alg = 1;
273         } else if (total_dsize < 262144) {
274             alg = 4;
275         } else if (total_dsize < 524288) {
276             alg = 1;
277         } else {
278             alg = 4;
279         }
280     } else if (communicator_size < 64) {
281         if (total_dsize < 512) {
282             alg = 3;
283         } else if (total_dsize < 524288) {
284             alg = 1;
285         } else {
286             alg = 4;
287         }
288     } else if (communicator_size < 128) {
289         if (total_dsize < 1024) {
290             alg = 3;
291         } else if (total_dsize < 2048) {
292             alg = 1;
293         } else if (total_dsize < 4096) {
294             alg = 4;
295         } else if (total_dsize < 262144) {
296             alg = 1;
297         } else {
298             alg = 2;
299         }
300     } else if (communicator_size < 256) {
301         if (total_dsize < 1024) {
302             alg = 3;
303         } else if (total_dsize < 2048) {
304             alg = 4;
305         } else if (total_dsize < 262144) {
306             alg = 1;
307         } else {
308             alg = 2;
309         }
310     } else if (communicator_size < 512) {
311         if (total_dsize < 1024) {
312             alg = 3;
313         } else if (total_dsize < 8192) {
314             alg = 4;
315         } else if (total_dsize < 32768) {
316             alg = 1;
317         } else {
318             alg = 2;
319         }
320     } else if (communicator_size < 1024) {
321         if (total_dsize < 512) {
322             alg = 3;
323         } else if (total_dsize < 8192) {
324             alg = 4;
325         } else if (total_dsize < 16384) {
326             alg = 1;
327         } else if (total_dsize < 131072) {
328             alg = 4;
329         } else if (total_dsize < 262144) {
330             alg = 1;
331         } else {
332             alg = 2;
333         }
334     } else if (communicator_size < 2048) {
335         if (total_dsize < 512) {
336             alg = 3;
337         } else if (total_dsize < 1024) {
338             alg = 4;
339         } else if (total_dsize < 2048) {
340             alg = 1;
341         } else if (total_dsize < 16384) {
342             alg = 4;
343         } else if (total_dsize < 262144) {
344             alg = 1;
345         } else {
346             alg = 4;
347         }
348     } else if (communicator_size < 4096) {
349         if (total_dsize < 1024) {
350             alg = 3;
351         } else if (total_dsize < 4096) {
352             alg = 4;
353         } else if (total_dsize < 8192) {
354             alg = 1;
355         } else if (total_dsize < 131072) {
356             alg = 4;
357         } else {
358             alg = 1;
359         }
360     } else {
361         if (total_dsize < 2048) {
362             alg = 3;
363         } else if (total_dsize < 8192) {
364             alg = 4;
365         } else if (total_dsize < 16384) {
366             alg = 1;
367         } else if (total_dsize < 32768) {
368             alg = 4;
369         } else if (total_dsize < 65536) {
370             alg = 1;
371         } else {
372             alg = 4;
373         }
374     }
375
376     return funcs[alg-1](sbuf, scount, sdtype,
377                           rbuf, rcount, rdtype, comm);
378 }
379
380 int alltoallv__ompi(const void *sbuf, const int *scounts, const int *sdisps,
381                     MPI_Datatype sdtype,
382                     void *rbuf, const int *rcounts, const int *rdisps,
383                     MPI_Datatype rdtype,
384                     MPI_Comm  comm
385                     )
386 {
387     int communicator_size = comm->size();
388     int alg = 1;
389     int (*funcs[])(const void *, const int*, const int*, MPI_Datatype, void*, const int*, const int*, MPI_Datatype, MPI_Comm) = {
390         &alltoallv__ompi_basic_linear,
391         &alltoallv__pair
392     };
393    /** Algorithms:
394      *  {1, "basic_linear"},
395      *  {2, "pairwise"},
396      *
397      * We can only optimize based on com size
398      */
399     if (communicator_size < 4) {
400         alg = 2;
401     } else if (communicator_size < 64) {
402         alg = 1;
403     } else if (communicator_size < 128) {
404         alg = 2;
405     } else if (communicator_size < 256) {
406         alg = 1;
407     } else if (communicator_size < 1024) {
408         alg = 2;
409     } else {
410         alg = 1;
411     }
412     return funcs[alg-1](sbuf, scounts, sdisps, sdtype,
413                            rbuf, rcounts, rdisps,rdtype,
414                            comm);
415 }
416
417 int barrier__ompi(MPI_Comm  comm)
418 {
419     int communicator_size = comm->size();
420     int alg = 1;
421     int (*funcs[])(MPI_Comm) = {
422         &barrier__ompi_basic_linear,
423         &barrier__ompi_basic_linear,
424         &barrier__ompi_recursivedoubling,
425         &barrier__ompi_bruck,
426         &barrier__ompi_two_procs,
427         &barrier__ompi_tree
428     };
429     /** Algorithms:
430      *  {1, "linear"},
431      *  {2, "double_ring"},
432      *  {3, "recursive_doubling"},
433      *  {4, "bruck"},
434      *  {5, "two_proc"},
435      *  {6, "tree"},
436      *
437      * We can only optimize based on com size
438      */
439     if (communicator_size < 4) {
440         alg = 3;
441     } else if (communicator_size < 8) {
442         alg = 1;
443     } else if (communicator_size < 64) {
444         alg = 3;
445     } else if (communicator_size < 256) {
446         alg = 4;
447     } else if (communicator_size < 512) {
448         alg = 6;
449     } else if (communicator_size < 1024) {
450         alg = 4;
451     } else if (communicator_size < 4096) {
452         alg = 6;
453     } else {
454         alg = 4;
455     }
456
457     return funcs[alg-1](comm);
458 }
459
460 int bcast__ompi(void *buff, int count, MPI_Datatype datatype, int root, MPI_Comm  comm)
461 {
462     int alg = 1;
463     size_t total_dsize, dsize;
464
465     int communicator_size = comm->size();
466
467     dsize = datatype->size();
468     total_dsize = dsize * (unsigned long)count;
469     int (*funcs[])(void*, int, MPI_Datatype, int, MPI_Comm) = {
470         &bcast__NTSL,
471         &bcast__ompi_pipeline,
472         &bcast__ompi_pipeline,
473         &bcast__ompi_split_bintree,
474         &bcast__NTSB,
475         &bcast__binomial_tree,
476         &bcast__mvapich2_knomial_intra_node,
477         &bcast__scatter_rdb_allgather,
478         &bcast__scatter_LR_allgather,
479     };
480     /** Algorithms:
481      *  {1, "basic_linear"},
482      *  {2, "chain"},
483      *  {3, "pipeline"},
484      *  {4, "split_binary_tree"},
485      *  {5, "binary_tree"},
486      *  {6, "binomial"},
487      *  {7, "knomial"},
488      *  {8, "scatter_allgather"},
489      *  {9, "scatter_allgather_ring"},
490      */
491     if (communicator_size < 4) {
492         if (total_dsize < 32) {
493             alg = 3;
494         } else if (total_dsize < 256) {
495             alg = 5;
496         } else if (total_dsize < 512) {
497             alg = 3;
498         } else if (total_dsize < 1024) {
499             alg = 7;
500         } else if (total_dsize < 32768) {
501             alg = 1;
502         } else if (total_dsize < 131072) {
503             alg = 5;
504         } else if (total_dsize < 262144) {
505             alg = 2;
506         } else if (total_dsize < 524288) {
507             alg = 1;
508         } else if (total_dsize < 1048576) {
509             alg = 6;
510         } else {
511             alg = 5;
512         }
513     } else if (communicator_size < 8) {
514         if (total_dsize < 64) {
515             alg = 5;
516         } else if (total_dsize < 128) {
517             alg = 6;
518         } else if (total_dsize < 2048) {
519             alg = 5;
520         } else if (total_dsize < 8192) {
521             alg = 6;
522         } else if (total_dsize < 1048576) {
523             alg = 1;
524         } else {
525             alg = 2;
526         }
527     } else if (communicator_size < 16) {
528         if (total_dsize < 8) {
529             alg = 7;
530         } else if (total_dsize < 64) {
531             alg = 5;
532         } else if (total_dsize < 4096) {
533             alg = 7;
534         } else if (total_dsize < 16384) {
535             alg = 5;
536         } else if (total_dsize < 32768) {
537             alg = 6;
538         } else {
539             alg = 1;
540         }
541     } else if (communicator_size < 32) {
542         if (total_dsize < 4096) {
543             alg = 7;
544         } else if (total_dsize < 1048576) {
545             alg = 6;
546         } else {
547             alg = 8;
548         }
549     } else if (communicator_size < 64) {
550         if (total_dsize < 2048) {
551             alg = 6;
552         } else {
553             alg = 7;
554         }
555     } else if (communicator_size < 128) {
556         alg = 7;
557     } else if (communicator_size < 256) {
558         if (total_dsize < 2) {
559             alg = 6;
560         } else if (total_dsize < 16384) {
561             alg = 5;
562         } else if (total_dsize < 32768) {
563             alg = 1;
564         } else if (total_dsize < 65536) {
565             alg = 5;
566         } else {
567             alg = 7;
568         }
569     } else if (communicator_size < 1024) {
570         if (total_dsize < 16384) {
571             alg = 7;
572         } else if (total_dsize < 32768) {
573             alg = 4;
574         } else {
575             alg = 7;
576         }
577     } else if (communicator_size < 2048) {
578         if (total_dsize < 524288) {
579             alg = 7;
580         } else {
581             alg = 8;
582         }
583     } else if (communicator_size < 4096) {
584         if (total_dsize < 262144) {
585             alg = 7;
586         } else {
587             alg = 8;
588         }
589     } else {
590         if (total_dsize < 8192) {
591             alg = 7;
592         } else if (total_dsize < 16384) {
593             alg = 5;
594         } else if (total_dsize < 262144) {
595             alg = 7;
596         } else {
597             alg = 8;
598         }
599     }
600     return funcs[alg-1](buff, count, datatype, root, comm);
601 }
602
603 int reduce__ompi(const void *sendbuf, void *recvbuf,
604                  int count, MPI_Datatype  datatype,
605                  MPI_Op   op, int root,
606                  MPI_Comm   comm)
607 {
608     size_t total_dsize, dsize;
609     int alg = 1;
610     int communicator_size = comm->size();
611
612     dsize=datatype->size();
613     total_dsize = dsize * count;
614     int (*funcs[])(const void*, void*, int, MPI_Datatype, MPI_Op, int, MPI_Comm) = {
615         &reduce__ompi_basic_linear,
616         &reduce__ompi_chain,
617         &reduce__ompi_pipeline,
618         &reduce__ompi_binary,
619         &reduce__ompi_binomial,
620         &reduce__ompi_in_order_binary,
621         //&reduce__rab our rab can't be used with all datatypes
622         &reduce__ompi_basic_linear
623     };
624     /** Algorithms:
625      *  {1, "linear"},
626      *  {2, "chain"},
627      *  {3, "pipeline"},
628      *  {4, "binary"},
629      *  {5, "binomial"},
630      *  {6, "in-order_binary"},
631      *  {7, "rabenseifner"},
632      *
633      * Currently, only linear and in-order binary tree algorithms are
634      * capable of non commutative ops.
635      */
636      if ((op != MPI_OP_NULL) && not op->is_commutative()) {
637         if (communicator_size < 4) {
638             if (total_dsize < 8) {
639                 alg = 6;
640             } else {
641                 alg = 1;
642             }
643         } else if (communicator_size < 8) {
644             alg = 1;
645         } else if (communicator_size < 16) {
646             if (total_dsize < 1024) {
647                 alg = 6;
648             } else if (total_dsize < 8192) {
649                 alg = 1;
650             } else if (total_dsize < 16384) {
651                 alg = 6;
652             } else if (total_dsize < 262144) {
653                 alg = 1;
654             } else {
655                 alg = 6;
656             }
657         } else if (communicator_size < 128) {
658             alg = 6;
659         } else if (communicator_size < 256) {
660             if (total_dsize < 512) {
661                 alg = 6;
662             } else if (total_dsize < 1024) {
663                 alg = 1;
664             } else {
665                 alg = 6;
666             }
667         } else {
668             alg = 6;
669         }
670     } else {
671         if (communicator_size < 4) {
672             if (total_dsize < 8) {
673                 alg = 7;
674             } else if (total_dsize < 16) {
675                 alg = 4;
676             } else if (total_dsize < 32) {
677                 alg = 3;
678             } else if (total_dsize < 262144) {
679                 alg = 1;
680             } else if (total_dsize < 524288) {
681                 alg = 3;
682             } else if (total_dsize < 1048576) {
683                 alg = 2;
684             } else {
685                 alg = 3;
686             }
687         } else if (communicator_size < 8) {
688             if (total_dsize < 4096) {
689                 alg = 4;
690             } else if (total_dsize < 65536) {
691                 alg = 2;
692             } else if (total_dsize < 262144) {
693                 alg = 5;
694             } else if (total_dsize < 524288) {
695                 alg = 1;
696             } else if (total_dsize < 1048576) {
697                 alg = 5;
698             } else {
699                 alg = 1;
700             }
701         } else if (communicator_size < 16) {
702             if (total_dsize < 8192) {
703                 alg = 4;
704             } else {
705                 alg = 5;
706             }
707         } else if (communicator_size < 32) {
708             if (total_dsize < 4096) {
709                 alg = 4;
710             } else {
711                 alg = 5;
712             }
713         } else if (communicator_size < 256) {
714             alg = 5;
715         } else if (communicator_size < 512) {
716             if (total_dsize < 8192) {
717                 alg = 5;
718             } else if (total_dsize < 16384) {
719                 alg = 6;
720             } else {
721                 alg = 5;
722             }
723         } else if (communicator_size < 2048) {
724             alg = 5;
725         } else if (communicator_size < 4096) {
726             if (total_dsize < 512) {
727                 alg = 5;
728             } else if (total_dsize < 1024) {
729                 alg = 6;
730             } else if (total_dsize < 8192) {
731                 alg = 5;
732             } else if (total_dsize < 16384) {
733                 alg = 6;
734             } else {
735                 alg = 5;
736             }
737         } else {
738             if (total_dsize < 16) {
739                 alg = 5;
740             } else if (total_dsize < 32) {
741                 alg = 6;
742             } else if (total_dsize < 1024) {
743                 alg = 5;
744             } else if (total_dsize < 2048) {
745                 alg = 6;
746             } else if (total_dsize < 8192) {
747                 alg = 5;
748             } else if (total_dsize < 16384) {
749                 alg = 6;
750             } else {
751                 alg = 5;
752             }
753         }
754     }
755
756     return funcs[alg-1] (sendbuf, recvbuf, count, datatype, op, root, comm);
757 }
758
759 int reduce_scatter__ompi(const void *sbuf, void *rbuf,
760                          const int *rcounts,
761                          MPI_Datatype dtype,
762                          MPI_Op  op,
763                          MPI_Comm  comm
764                          )
765 {
766     size_t total_dsize, dsize;
767     int communicator_size = comm->size();
768     int alg = 1;
769     int zerocounts = 0;
770     dsize=dtype->size();
771     total_dsize = 0;
772     for (int i = 0; i < communicator_size; i++) {
773         total_dsize += rcounts[i];
774        // if (0 == rcounts[i]) {
775         //    zerocounts = 1;
776         //}
777     }
778     total_dsize *= dsize;
779     int (*funcs[])(const void*, void*, const int*, MPI_Datatype, MPI_Op, MPI_Comm) = {
780         &reduce_scatter__default,
781         &reduce_scatter__ompi_basic_recursivehalving,
782         &reduce_scatter__ompi_ring,
783         &reduce_scatter__ompi_ring,
784     };
785     /** Algorithms:
786      *  {1, "non-overlapping"},
787      *  {2, "recursive_halving"},
788      *  {3, "ring"},
789      *  {4, "butterfly"},
790      *
791      * Non commutative algorithm capability needs re-investigation.
792      * Defaulting to non overlapping for non commutative ops.
793      */
794     if (((op != MPI_OP_NULL) && not op->is_commutative()) || (zerocounts)) {
795         alg = 1;
796     } else {
797         if (communicator_size < 4) {
798             if (total_dsize < 65536) {
799                 alg = 3;
800             } else if (total_dsize < 131072) {
801                 alg = 4;
802             } else {
803                 alg = 3;
804             }
805         } else if (communicator_size < 8) {
806             if (total_dsize < 8) {
807                 alg = 1;
808             } else if (total_dsize < 262144) {
809                 alg = 2;
810             } else {
811                 alg = 3;
812             }
813         } else if (communicator_size < 32) {
814             if (total_dsize < 262144) {
815                 alg = 2;
816             } else {
817                 alg = 3;
818             }
819         } else if (communicator_size < 64) {
820             if (total_dsize < 64) {
821                 alg = 1;
822             } else if (total_dsize < 2048) {
823                 alg = 2;
824             } else if (total_dsize < 524288) {
825                 alg = 4;
826             } else {
827                 alg = 3;
828             }
829         } else if (communicator_size < 128) {
830             if (total_dsize < 256) {
831                 alg = 1;
832             } else if (total_dsize < 512) {
833                 alg = 2;
834             } else if (total_dsize < 2048) {
835                 alg = 4;
836             } else if (total_dsize < 4096) {
837                 alg = 2;
838             } else {
839                 alg = 4;
840             }
841         } else if (communicator_size < 256) {
842             if (total_dsize < 256) {
843                 alg = 1;
844             } else if (total_dsize < 512) {
845                 alg = 2;
846             } else {
847                 alg = 4;
848             }
849         } else if (communicator_size < 512) {
850             if (total_dsize < 256) {
851                 alg = 1;
852             } else if (total_dsize < 1024) {
853                 alg = 2;
854             } else {
855                 alg = 4;
856             }
857         } else if (communicator_size < 1024) {
858             if (total_dsize < 512) {
859                 alg = 1;
860             } else if (total_dsize < 2048) {
861                 alg = 2;
862             } else if (total_dsize < 8192) {
863                 alg = 4;
864             } else if (total_dsize < 16384) {
865                 alg = 2;
866             } else {
867                 alg = 4;
868             }
869         } else if (communicator_size < 2048) {
870             if (total_dsize < 512) {
871                 alg = 1;
872             } else if (total_dsize < 4096) {
873                 alg = 2;
874             } else if (total_dsize < 16384) {
875                 alg = 4;
876             } else if (total_dsize < 32768) {
877                 alg = 2;
878             } else {
879                 alg = 4;
880             }
881         } else if (communicator_size < 4096) {
882             if (total_dsize < 512) {
883                 alg = 1;
884             } else if (total_dsize < 4096) {
885                 alg = 2;
886             } else {
887                 alg = 4;
888             }
889         } else {
890             if (total_dsize < 1024) {
891                 alg = 1;
892             } else if (total_dsize < 8192) {
893                 alg = 2;
894             } else {
895                 alg = 4;
896             }
897         }
898     }
899
900     return funcs[alg-1] (sbuf, rbuf, rcounts, dtype, op, comm);
901 }
902
903 int allgather__ompi(const void *sbuf, int scount,
904                     MPI_Datatype sdtype,
905                     void* rbuf, int rcount,
906                     MPI_Datatype rdtype,
907                     MPI_Comm  comm
908                     )
909 {
910     int communicator_size;
911     size_t dsize, total_dsize;
912     int alg = 1;
913     communicator_size = comm->size();
914     if (MPI_IN_PLACE != sbuf) {
915         dsize = sdtype->size();
916     } else {
917         dsize = rdtype->size();
918     }
919     total_dsize = dsize * (ptrdiff_t)scount;
920     int (*funcs[])(const void*, int, MPI_Datatype, void*, int, MPI_Datatype, MPI_Comm) = {
921         &allgather__NTSLR_NB,
922         &allgather__bruck,
923         &allgather__rdb,
924         &allgather__ring,
925         &allgather__ompi_neighborexchange,
926         &allgather__pair
927     };
928     /** Algorithms:
929      *  {1, "linear"},
930      *  {2, "bruck"},
931      *  {3, "recursive_doubling"},
932      *  {4, "ring"},
933      *  {5, "neighbor"},
934      *  {6, "two_proc"}
935      */
936     if (communicator_size == 2) {
937         alg = 6;
938     } else if (communicator_size < 32) {
939         alg = 3;
940     } else if (communicator_size < 64) {
941         if (total_dsize < 1024) {
942             alg = 3;
943         } else if (total_dsize < 65536) {
944             alg = 5;
945         } else {
946             alg = 4;
947         }
948     } else if (communicator_size < 128) {
949         if (total_dsize < 512) {
950             alg = 3;
951         } else if (total_dsize < 65536) {
952             alg = 5;
953         } else {
954             alg = 4;
955         }
956     } else if (communicator_size < 256) {
957         if (total_dsize < 512) {
958             alg = 3;
959         } else if (total_dsize < 131072) {
960             alg = 5;
961         } else if (total_dsize < 524288) {
962             alg = 4;
963         } else if (total_dsize < 1048576) {
964             alg = 5;
965         } else {
966             alg = 4;
967         }
968     } else if (communicator_size < 512) {
969         if (total_dsize < 32) {
970             alg = 3;
971         } else if (total_dsize < 128) {
972             alg = 2;
973         } else if (total_dsize < 1024) {
974             alg = 3;
975         } else if (total_dsize < 131072) {
976             alg = 5;
977         } else if (total_dsize < 524288) {
978             alg = 4;
979         } else if (total_dsize < 1048576) {
980             alg = 5;
981         } else {
982             alg = 4;
983         }
984     } else if (communicator_size < 1024) {
985         if (total_dsize < 64) {
986             alg = 3;
987         } else if (total_dsize < 256) {
988             alg = 2;
989         } else if (total_dsize < 2048) {
990             alg = 3;
991         } else {
992             alg = 5;
993         }
994     } else if (communicator_size < 2048) {
995         if (total_dsize < 4) {
996             alg = 3;
997         } else if (total_dsize < 8) {
998             alg = 2;
999         } else if (total_dsize < 16) {
1000             alg = 3;
1001         } else if (total_dsize < 32) {
1002             alg = 2;
1003         } else if (total_dsize < 256) {
1004             alg = 3;
1005         } else if (total_dsize < 512) {
1006             alg = 2;
1007         } else if (total_dsize < 4096) {
1008             alg = 3;
1009         } else {
1010             alg = 5;
1011         }
1012     } else if (communicator_size < 4096) {
1013         if (total_dsize < 32) {
1014             alg = 2;
1015         } else if (total_dsize < 128) {
1016             alg = 3;
1017         } else if (total_dsize < 512) {
1018             alg = 2;
1019         } else if (total_dsize < 4096) {
1020             alg = 3;
1021         } else {
1022             alg = 5;
1023         }
1024     } else {
1025         if (total_dsize < 2) {
1026             alg = 3;
1027         } else if (total_dsize < 8) {
1028             alg = 2;
1029         } else if (total_dsize < 16) {
1030             alg = 3;
1031         } else if (total_dsize < 512) {
1032             alg = 2;
1033         } else if (total_dsize < 4096) {
1034             alg = 3;
1035         } else {
1036             alg = 5;
1037         }
1038     }
1039
1040     return funcs[alg-1](sbuf, scount, sdtype, rbuf, rcount, rdtype, comm);
1041
1042 }
1043
1044 int allgatherv__ompi(const void *sbuf, int scount,
1045                      MPI_Datatype sdtype,
1046                      void* rbuf, const int *rcounts,
1047                      const int *rdispls,
1048                      MPI_Datatype rdtype,
1049                      MPI_Comm  comm
1050                      )
1051 {
1052     int i;
1053     int communicator_size;
1054     size_t dsize, total_dsize;
1055     int alg = 1;
1056     communicator_size = comm->size();
1057     if (MPI_IN_PLACE != sbuf) {
1058         dsize = sdtype->size();
1059     } else {
1060         dsize = rdtype->size();
1061     }
1062
1063     total_dsize = 0;
1064     for (i = 0; i < communicator_size; i++) {
1065         total_dsize += dsize * rcounts[i];
1066     }
1067
1068     /* use the per-rank data size as basis, similar to allgather */
1069     size_t per_rank_dsize = total_dsize / communicator_size;
1070
1071     int (*funcs[])(const void*, int, MPI_Datatype, void*, const int*, const int*, MPI_Datatype, MPI_Comm) = {
1072         &allgatherv__GB,
1073         &allgatherv__ompi_bruck,
1074         &allgatherv__mpich_ring,
1075         &allgatherv__ompi_neighborexchange,
1076         &allgatherv__pair
1077     };
1078     /** Algorithms:
1079      *  {1, "default"},
1080      *  {2, "bruck"},
1081      *  {3, "ring"},
1082      *  {4, "neighbor"},
1083      *  {5, "two_proc"},
1084      */
1085     if (communicator_size == 2) {
1086         if (per_rank_dsize < 2048) {
1087             alg = 3;
1088         } else if (per_rank_dsize < 4096) {
1089             alg = 5;
1090         } else if (per_rank_dsize < 8192) {
1091             alg = 3;
1092         } else {
1093             alg = 5;
1094         }
1095     } else if (communicator_size < 8) {
1096         if (per_rank_dsize < 256) {
1097             alg = 1;
1098         } else if (per_rank_dsize < 4096) {
1099             alg = 4;
1100         } else if (per_rank_dsize < 8192) {
1101             alg = 3;
1102         } else if (per_rank_dsize < 16384) {
1103             alg = 4;
1104         } else if (per_rank_dsize < 262144) {
1105             alg = 2;
1106         } else {
1107             alg = 4;
1108         }
1109     } else if (communicator_size < 16) {
1110         if (per_rank_dsize < 1024) {
1111             alg = 1;
1112         } else {
1113             alg = 2;
1114         }
1115     } else if (communicator_size < 32) {
1116         if (per_rank_dsize < 128) {
1117             alg = 1;
1118         } else if (per_rank_dsize < 262144) {
1119             alg = 2;
1120         } else {
1121             alg = 3;
1122         }
1123     } else if (communicator_size < 64) {
1124         if (per_rank_dsize < 256) {
1125             alg = 1;
1126         } else if (per_rank_dsize < 8192) {
1127             alg = 2;
1128         } else {
1129             alg = 3;
1130         }
1131     } else if (communicator_size < 128) {
1132         if (per_rank_dsize < 256) {
1133             alg = 1;
1134         } else if (per_rank_dsize < 4096) {
1135             alg = 2;
1136         } else {
1137             alg = 3;
1138         }
1139     } else if (communicator_size < 256) {
1140         if (per_rank_dsize < 1024) {
1141             alg = 2;
1142         } else if (per_rank_dsize < 65536) {
1143             alg = 4;
1144         } else {
1145             alg = 3;
1146         }
1147     } else if (communicator_size < 512) {
1148         if (per_rank_dsize < 1024) {
1149             alg = 2;
1150         } else {
1151             alg = 3;
1152         }
1153     } else if (communicator_size < 1024) {
1154         if (per_rank_dsize < 512) {
1155             alg = 2;
1156         } else if (per_rank_dsize < 1024) {
1157             alg = 1;
1158         } else if (per_rank_dsize < 4096) {
1159             alg = 2;
1160         } else if (per_rank_dsize < 1048576) {
1161             alg = 4;
1162         } else {
1163             alg = 3;
1164         }
1165     } else {
1166         if (per_rank_dsize < 4096) {
1167             alg = 2;
1168         } else {
1169             alg = 4;
1170         }
1171     }
1172
1173     return funcs[alg-1](sbuf, scount, sdtype, rbuf, rcounts, rdispls, rdtype, comm);
1174 }
1175
1176 int gather__ompi(const void *sbuf, int scount,
1177                  MPI_Datatype sdtype,
1178                  void* rbuf, int rcount,
1179                  MPI_Datatype rdtype,
1180                  int root,
1181                  MPI_Comm  comm
1182                  )
1183 {
1184     int communicator_size, rank;
1185     size_t dsize, total_dsize;
1186     int alg = 1;
1187     communicator_size = comm->size();
1188     rank = comm->rank();
1189
1190     if (rank == root) {
1191         dsize = rdtype->size();
1192         total_dsize = dsize * rcount;
1193     } else {
1194         dsize = sdtype->size();
1195         total_dsize = dsize * scount;
1196     }
1197     int (*funcs[])(const void*, int, MPI_Datatype, void*, int, MPI_Datatype, int, MPI_Comm) = {
1198         &gather__ompi_basic_linear,
1199         &gather__ompi_binomial,
1200         &gather__ompi_linear_sync
1201     };
1202     /** Algorithms:
1203      *  {1, "basic_linear"},
1204      *  {2, "binomial"},
1205      *  {3, "linear_sync"},
1206      *
1207      * We do not make any rank specific checks since the params
1208      * should be uniform across ranks.
1209      */
1210     if (communicator_size < 4) {
1211         if (total_dsize < 2) {
1212             alg = 3;
1213         } else if (total_dsize < 4) {
1214             alg = 1;
1215         } else if (total_dsize < 32768) {
1216             alg = 2;
1217         } else if (total_dsize < 65536) {
1218             alg = 1;
1219         } else if (total_dsize < 131072) {
1220             alg = 2;
1221         } else {
1222             alg = 3;
1223         }
1224     } else if (communicator_size < 8) {
1225         if (total_dsize < 1024) {
1226             alg = 2;
1227         } else if (total_dsize < 8192) {
1228             alg = 1;
1229         } else if (total_dsize < 32768) {
1230             alg = 2;
1231         } else if (total_dsize < 262144) {
1232             alg = 1;
1233         } else {
1234             alg = 3;
1235         }
1236     } else if (communicator_size < 256) {
1237         alg = 2;
1238     } else if (communicator_size < 512) {
1239         if (total_dsize < 2048) {
1240             alg = 2;
1241         } else if (total_dsize < 8192) {
1242             alg = 1;
1243         } else {
1244             alg = 2;
1245         }
1246     } else {
1247         alg = 2;
1248     }
1249
1250     return funcs[alg-1](sbuf, scount, sdtype, rbuf, rcount, rdtype, root, comm);
1251 }
1252
1253
1254 int scatter__ompi(const void *sbuf, int scount,
1255                   MPI_Datatype sdtype,
1256                   void* rbuf, int rcount,
1257                   MPI_Datatype rdtype,
1258                   int root, MPI_Comm  comm
1259                   )
1260 {
1261     int communicator_size, rank;
1262     size_t dsize, total_dsize;
1263     int alg = 1;
1264
1265     communicator_size = comm->size();
1266     rank = comm->rank();
1267     if (root == rank) {
1268         dsize=sdtype->size();
1269         total_dsize = dsize * scount;
1270     } else {
1271         dsize=rdtype->size();
1272         total_dsize = dsize * rcount;
1273     }
1274     int (*funcs[])(const void*, int, MPI_Datatype, void*, int, MPI_Datatype, int, MPI_Comm) = {
1275         &scatter__ompi_basic_linear,
1276         &scatter__ompi_binomial,
1277         &scatter__ompi_basic_linear
1278     };
1279     /** Algorithms:
1280      *  {1, "basic_linear"},
1281      *  {2, "binomial"},
1282      *  {3, "linear_nb"},
1283      *
1284      * We do not make any rank specific checks since the params
1285      * should be uniform across ranks.
1286      */
1287     if (communicator_size < 4) {
1288         if (total_dsize < 2) {
1289             alg = 3;
1290         } else if (total_dsize < 131072) {
1291             alg = 1;
1292         } else if (total_dsize < 262144) {
1293             alg = 3;
1294         } else {
1295             alg = 1;
1296         }
1297     } else if (communicator_size < 8) {
1298         if (total_dsize < 2048) {
1299             alg = 2;
1300         } else if (total_dsize < 4096) {
1301             alg = 1;
1302         } else if (total_dsize < 8192) {
1303             alg = 2;
1304         } else if (total_dsize < 32768) {
1305             alg = 1;
1306         } else if (total_dsize < 1048576) {
1307             alg = 3;
1308         } else {
1309             alg = 1;
1310         }
1311     } else if (communicator_size < 16) {
1312         if (total_dsize < 16384) {
1313             alg = 2;
1314         } else if (total_dsize < 1048576) {
1315             alg = 3;
1316         } else {
1317             alg = 1;
1318         }
1319     } else if (communicator_size < 32) {
1320         if (total_dsize < 16384) {
1321             alg = 2;
1322         } else if (total_dsize < 32768) {
1323             alg = 1;
1324         } else {
1325             alg = 3;
1326         }
1327     } else if (communicator_size < 64) {
1328         if (total_dsize < 512) {
1329             alg = 2;
1330         } else if (total_dsize < 8192) {
1331             alg = 3;
1332         } else if (total_dsize < 16384) {
1333             alg = 2;
1334         } else {
1335             alg = 3;
1336         }
1337     } else {
1338         if (total_dsize < 512) {
1339             alg = 2;
1340         } else {
1341             alg = 3;
1342         }
1343     }
1344
1345     return funcs[alg-1](sbuf, scount, sdtype, rbuf, rcount, rdtype, root, comm);
1346 }
1347
1348 }
1349 }