Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[codacy/cppcheck] Fix: Variable is reassigned a value before the old one has been...
[simgrid.git] / src / smpi / colls / smpi_mvapich2_selector.cpp
1 /* selector for collective algorithms based on mvapich decision logic */
2
3 /* Copyright (c) 2009-2019. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include "colls_private.hpp"
10
11 #include "smpi_mvapich2_selector_stampede.hpp"
12
13 namespace simgrid{
14 namespace smpi{
15
16
17 int Coll_alltoall_mvapich2::alltoall( void *sendbuf, int sendcount,
18     MPI_Datatype sendtype,
19     void* recvbuf, int recvcount,
20     MPI_Datatype recvtype,
21     MPI_Comm comm)
22 {
23
24   if(mv2_alltoall_table_ppn_conf==NULL)
25     init_mv2_alltoall_tables_stampede();
26
27   int sendtype_size, recvtype_size, comm_size;
28   char * tmp_buf = NULL;
29   int mpi_errno=MPI_SUCCESS;
30   int range = 0;
31   int range_threshold = 0;
32   int conf_index = 0;
33   comm_size =  comm->size();
34
35   sendtype_size=sendtype->size();
36   recvtype_size=recvtype->size();
37   long nbytes = sendtype_size * sendcount;
38
39   /* check if safe to use partial subscription mode */
40
41   /* Search for the corresponding system size inside the tuning table */
42   while ((range < (mv2_size_alltoall_tuning_table[conf_index] - 1)) &&
43       (comm_size > mv2_alltoall_thresholds_table[conf_index][range].numproc)) {
44       range++;
45   }
46   /* Search for corresponding inter-leader function */
47   while ((range_threshold < (mv2_alltoall_thresholds_table[conf_index][range].size_table - 1))
48       && (nbytes >
49   mv2_alltoall_thresholds_table[conf_index][range].algo_table[range_threshold].max)
50   && (mv2_alltoall_thresholds_table[conf_index][range].algo_table[range_threshold].max != -1)) {
51       range_threshold++;
52   }
53   MV2_Alltoall_function = mv2_alltoall_thresholds_table[conf_index][range].algo_table[range_threshold]
54                                                                                       .MV2_pt_Alltoall_function;
55
56   if(sendbuf != MPI_IN_PLACE) {
57       mpi_errno = MV2_Alltoall_function(sendbuf, sendcount, sendtype,
58           recvbuf, recvcount, recvtype,
59           comm);
60   } else {
61       range_threshold = 0;
62       if(nbytes <
63           mv2_alltoall_thresholds_table[conf_index][range].in_place_algo_table[range_threshold].min
64           ||nbytes > mv2_alltoall_thresholds_table[conf_index][range].in_place_algo_table[range_threshold].max
65       ) {
66           tmp_buf = (char *)smpi_get_tmp_sendbuffer( comm_size * recvcount * recvtype_size );
67           Datatype::copy((char *)recvbuf,
68               comm_size*recvcount, recvtype,
69               (char *)tmp_buf,
70               comm_size*recvcount, recvtype);
71
72           mpi_errno = MV2_Alltoall_function(tmp_buf, recvcount, recvtype,
73               recvbuf, recvcount, recvtype,
74               comm );
75           smpi_free_tmp_buffer(tmp_buf);
76       } else {
77           mpi_errno = MPIR_Alltoall_inplace_MV2(sendbuf, sendcount, sendtype,
78               recvbuf, recvcount, recvtype,
79               comm );
80       }
81   }
82
83
84   return (mpi_errno);
85 }
86
87 int Coll_allgather_mvapich2::allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
88     void *recvbuf, int recvcount, MPI_Datatype recvtype,
89     MPI_Comm comm)
90 {
91
92   int mpi_errno = MPI_SUCCESS;
93   long nbytes = 0, comm_size, recvtype_size;
94   int range = 0;
95   int partial_sub_ok = 0;
96   int conf_index = 0;
97   int range_threshold = 0;
98   int is_two_level = 0;
99   MPI_Comm shmem_comm;
100   //MPI_Comm *shmem_commptr=NULL;
101   /* Get the size of the communicator */
102   comm_size = comm->size();
103   recvtype_size=recvtype->size();
104   nbytes = recvtype_size * recvcount;
105
106   if(mv2_allgather_table_ppn_conf==NULL)
107     init_mv2_allgather_tables_stampede();
108
109   if(comm->get_leaders_comm()==MPI_COMM_NULL){
110     comm->init_smp();
111   }
112
113   if (comm->is_uniform()){
114     shmem_comm = comm->get_intra_comm();
115     int local_size = shmem_comm->size();
116     int i          = 0;
117     if (mv2_allgather_table_ppn_conf[0] == -1) {
118       // Indicating user defined tuning
119       conf_index = 0;
120       goto conf_check_end;
121     }
122     do {
123       if (local_size == mv2_allgather_table_ppn_conf[i]) {
124         conf_index = i;
125         partial_sub_ok = 1;
126         break;
127       }
128       i++;
129     } while(i < mv2_allgather_num_ppn_conf);
130   }
131   conf_check_end:
132   if (partial_sub_ok != 1) {
133     conf_index = 0;
134   }
135
136   /* Search for the corresponding system size inside the tuning table */
137   while ((range < (mv2_size_allgather_tuning_table[conf_index] - 1)) &&
138       (comm_size >
139   mv2_allgather_thresholds_table[conf_index][range].numproc)) {
140       range++;
141   }
142   /* Search for corresponding inter-leader function */
143   while ((range_threshold <
144       (mv2_allgather_thresholds_table[conf_index][range].size_inter_table - 1))
145       && (nbytes > mv2_allgather_thresholds_table[conf_index][range].inter_leader[range_threshold].max)
146       && (mv2_allgather_thresholds_table[conf_index][range].inter_leader[range_threshold].max !=
147           -1)) {
148       range_threshold++;
149   }
150
151   /* Set inter-leader pt */
152   MV2_Allgatherction =
153       mv2_allgather_thresholds_table[conf_index][range].inter_leader[range_threshold].
154       MV2_pt_Allgatherction;
155
156   is_two_level =  mv2_allgather_thresholds_table[conf_index][range].two_level[range_threshold];
157
158   /* intracommunicator */
159   if(is_two_level ==1){
160     if(partial_sub_ok ==1){
161       if (comm->is_blocked()){
162       mpi_errno = MPIR_2lvl_Allgather_MV2(sendbuf, sendcount, sendtype,
163                             recvbuf, recvcount, recvtype,
164                             comm);
165       }else{
166       mpi_errno = Coll_allgather_mpich::allgather(sendbuf, sendcount, sendtype,
167                             recvbuf, recvcount, recvtype,
168                             comm);
169       }
170     } else {
171       mpi_errno = MPIR_Allgather_RD_MV2(sendbuf, sendcount, sendtype,
172           recvbuf, recvcount, recvtype,
173           comm);
174     }
175   } else if(MV2_Allgatherction == &MPIR_Allgather_Bruck_MV2
176       || MV2_Allgatherction == &MPIR_Allgather_RD_MV2
177       || MV2_Allgatherction == &MPIR_Allgather_Ring_MV2) {
178       mpi_errno = MV2_Allgatherction(sendbuf, sendcount, sendtype,
179           recvbuf, recvcount, recvtype,
180           comm);
181   }else{
182       return MPI_ERR_OTHER;
183   }
184
185   return mpi_errno;
186 }
187
188 int Coll_gather_mvapich2::gather(void *sendbuf,
189     int sendcnt,
190     MPI_Datatype sendtype,
191     void *recvbuf,
192     int recvcnt,
193     MPI_Datatype recvtype,
194     int root, MPI_Comm  comm)
195 {
196   if(mv2_gather_thresholds_table==NULL)
197     init_mv2_gather_tables_stampede();
198
199   int mpi_errno = MPI_SUCCESS;
200   int range = 0;
201   int range_threshold = 0;
202   int range_intra_threshold = 0;
203   long nbytes = 0;
204   int recvtype_size, sendtype_size;
205   int comm_size = comm->size();
206   int rank      = comm->rank();
207
208   if (rank == root) {
209       recvtype_size=recvtype->size();
210       nbytes = recvcnt * recvtype_size;
211   } else {
212       sendtype_size=sendtype->size();
213       nbytes = sendcnt * sendtype_size;
214   }
215
216   /* Search for the corresponding system size inside the tuning table */
217   while ((range < (mv2_size_gather_tuning_table - 1)) &&
218       (comm_size > mv2_gather_thresholds_table[range].numproc)) {
219       range++;
220   }
221   /* Search for corresponding inter-leader function */
222   while ((range_threshold < (mv2_gather_thresholds_table[range].size_inter_table - 1))
223       && (nbytes >
224   mv2_gather_thresholds_table[range].inter_leader[range_threshold].max)
225   && (mv2_gather_thresholds_table[range].inter_leader[range_threshold].max !=
226       -1)) {
227       range_threshold++;
228   }
229
230   /* Search for corresponding intra node function */
231   while ((range_intra_threshold < (mv2_gather_thresholds_table[range].size_intra_table - 1))
232       && (nbytes >
233   mv2_gather_thresholds_table[range].intra_node[range_intra_threshold].max)
234   && (mv2_gather_thresholds_table[range].intra_node[range_intra_threshold].max !=
235       -1)) {
236       range_intra_threshold++;
237   }
238
239     if (comm->is_blocked() ) {
240         // Set intra-node function pt for gather_two_level
241         MV2_Gather_intra_node_function =
242                               mv2_gather_thresholds_table[range].intra_node[range_intra_threshold].
243                               MV2_pt_Gather_function;
244         //Set inter-leader pt
245         MV2_Gather_inter_leader_function =
246                               mv2_gather_thresholds_table[range].inter_leader[range_threshold].
247                               MV2_pt_Gather_function;
248         // We call Gather function
249         mpi_errno =
250             MV2_Gather_inter_leader_function(sendbuf, sendcnt, sendtype, recvbuf, recvcnt,
251                                              recvtype, root, comm);
252
253     } else {
254   // Indeed, direct (non SMP-aware)gather is MPICH one
255   mpi_errno = Coll_gather_mpich::gather(sendbuf, sendcnt, sendtype,
256       recvbuf, recvcnt, recvtype,
257       root, comm);
258   }
259
260   return mpi_errno;
261 }
262
263 int Coll_allgatherv_mvapich2::allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
264     void *recvbuf, int *recvcounts, int *displs,
265     MPI_Datatype recvtype, MPI_Comm  comm )
266 {
267   int mpi_errno = MPI_SUCCESS;
268   int range = 0, comm_size, total_count, recvtype_size, i;
269   int range_threshold = 0;
270   long nbytes = 0;
271
272   if(mv2_allgatherv_thresholds_table==NULL)
273     init_mv2_allgatherv_tables_stampede();
274
275   comm_size = comm->size();
276   total_count = 0;
277   for (i = 0; i < comm_size; i++)
278     total_count += recvcounts[i];
279
280   recvtype_size=recvtype->size();
281   nbytes = total_count * recvtype_size;
282
283   /* Search for the corresponding system size inside the tuning table */
284   while ((range < (mv2_size_allgatherv_tuning_table - 1)) &&
285       (comm_size > mv2_allgatherv_thresholds_table[range].numproc)) {
286       range++;
287   }
288   /* Search for corresponding inter-leader function */
289   while ((range_threshold < (mv2_allgatherv_thresholds_table[range].size_inter_table - 1))
290       && (nbytes >
291   comm_size * mv2_allgatherv_thresholds_table[range].inter_leader[range_threshold].max)
292   && (mv2_allgatherv_thresholds_table[range].inter_leader[range_threshold].max !=
293       -1)) {
294       range_threshold++;
295   }
296   /* Set inter-leader pt */
297   MV2_Allgatherv_function =
298       mv2_allgatherv_thresholds_table[range].inter_leader[range_threshold].
299       MV2_pt_Allgatherv_function;
300
301   if (MV2_Allgatherv_function == &MPIR_Allgatherv_Rec_Doubling_MV2)
302     {
303     if (not(comm_size & (comm_size - 1))) {
304       mpi_errno =
305           MPIR_Allgatherv_Rec_Doubling_MV2(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm);
306         } else {
307             mpi_errno =
308                 MPIR_Allgatherv_Bruck_MV2(sendbuf, sendcount,
309                     sendtype, recvbuf,
310                     recvcounts, displs,
311                     recvtype, comm);
312         }
313     } else {
314         mpi_errno =
315             MV2_Allgatherv_function(sendbuf, sendcount, sendtype,
316                 recvbuf, recvcounts, displs,
317                 recvtype, comm);
318     }
319
320   return mpi_errno;
321 }
322
323
324
325 int Coll_allreduce_mvapich2::allreduce(void *sendbuf,
326     void *recvbuf,
327     int count,
328     MPI_Datatype datatype,
329     MPI_Op op, MPI_Comm comm)
330 {
331
332   int mpi_errno = MPI_SUCCESS;
333   //int rank = 0,
334   int comm_size = 0;
335
336   comm_size = comm->size();
337   //rank = comm->rank();
338
339   if (count == 0) {
340       return MPI_SUCCESS;
341   }
342
343   if (mv2_allreduce_thresholds_table == NULL)
344     init_mv2_allreduce_tables_stampede();
345
346   /* check if multiple threads are calling this collective function */
347
348   MPI_Aint sendtype_size = 0;
349   long nbytes = 0;
350   int is_commutative = 0;
351   MPI_Aint true_lb, true_extent;
352
353   sendtype_size=datatype->size();
354   nbytes = count * sendtype_size;
355
356   datatype->extent(&true_lb, &true_extent);
357   //MPI_Op *op_ptr;
358   //is_commutative = op->is_commutative();
359
360   {
361     int range = 0, range_threshold = 0, range_threshold_intra = 0;
362     int is_two_level = 0;
363
364     /* Search for the corresponding system size inside the tuning table */
365     while ((range < (mv2_size_allreduce_tuning_table - 1)) &&
366         (comm_size > mv2_allreduce_thresholds_table[range].numproc)) {
367         range++;
368     }
369     /* Search for corresponding inter-leader function */
370     /* skip mcast poiters if mcast is not available */
371     if(mv2_allreduce_thresholds_table[range].mcast_enabled != 1){
372         while ((range_threshold < (mv2_allreduce_thresholds_table[range].size_inter_table - 1))
373             && ((mv2_allreduce_thresholds_table[range].
374                 inter_leader[range_threshold].MV2_pt_Allreducection
375                 == &MPIR_Allreduce_mcst_reduce_redscat_gather_MV2) ||
376                 (mv2_allreduce_thresholds_table[range].
377                     inter_leader[range_threshold].MV2_pt_Allreducection
378                     == &MPIR_Allreduce_mcst_reduce_two_level_helper_MV2)
379             )) {
380             range_threshold++;
381         }
382     }
383     while ((range_threshold < (mv2_allreduce_thresholds_table[range].size_inter_table - 1))
384         && (nbytes >
385     mv2_allreduce_thresholds_table[range].inter_leader[range_threshold].max)
386     && (mv2_allreduce_thresholds_table[range].inter_leader[range_threshold].max != -1)) {
387         range_threshold++;
388     }
389     if(mv2_allreduce_thresholds_table[range].is_two_level_allreduce[range_threshold] == 1){
390         is_two_level = 1;
391     }
392     /* Search for corresponding intra-node function */
393     while ((range_threshold_intra <
394         (mv2_allreduce_thresholds_table[range].size_intra_table - 1))
395         && (nbytes >
396     mv2_allreduce_thresholds_table[range].intra_node[range_threshold_intra].max)
397     && (mv2_allreduce_thresholds_table[range].intra_node[range_threshold_intra].max !=
398         -1)) {
399         range_threshold_intra++;
400     }
401
402     MV2_Allreducection = mv2_allreduce_thresholds_table[range].inter_leader[range_threshold]
403                                                                                 .MV2_pt_Allreducection;
404
405     MV2_Allreduce_intra_function = mv2_allreduce_thresholds_table[range].intra_node[range_threshold_intra]
406                                                                                     .MV2_pt_Allreducection;
407
408     /* check if mcast is ready, otherwise replace mcast with other algorithm */
409     if((MV2_Allreducection == &MPIR_Allreduce_mcst_reduce_redscat_gather_MV2)||
410         (MV2_Allreducection == &MPIR_Allreduce_mcst_reduce_two_level_helper_MV2)){
411         {
412           MV2_Allreducection = &MPIR_Allreduce_pt2pt_rd_MV2;
413         }
414         if(is_two_level != 1) {
415             MV2_Allreducection = &MPIR_Allreduce_pt2pt_rd_MV2;
416         }
417     }
418
419     if(is_two_level == 1){
420         // check if shm is ready, if not use other algorithm first
421         if (is_commutative) {
422           if(comm->get_leaders_comm()==MPI_COMM_NULL){
423             comm->init_smp();
424           }
425           mpi_errno = MPIR_Allreduce_two_level_MV2(sendbuf, recvbuf, count,
426                                                      datatype, op, comm);
427                 } else {
428         mpi_errno = MPIR_Allreduce_pt2pt_rd_MV2(sendbuf, recvbuf, count,
429             datatype, op, comm);
430         }
431     } else {
432         mpi_errno = MV2_Allreducection(sendbuf, recvbuf, count,
433             datatype, op, comm);
434     }
435   }
436
437   //comm->ch.intra_node_done=0;
438
439   return (mpi_errno);
440
441
442 }
443
444
445 int Coll_alltoallv_mvapich2::alltoallv(void *sbuf, int *scounts, int *sdisps,
446     MPI_Datatype sdtype,
447     void *rbuf, int *rcounts, int *rdisps,
448     MPI_Datatype rdtype,
449     MPI_Comm  comm
450 )
451 {
452
453   if (sbuf == MPI_IN_PLACE) {
454       return Coll_alltoallv_ompi_basic_linear::alltoallv(sbuf, scounts, sdisps, sdtype,
455           rbuf, rcounts, rdisps,rdtype,
456           comm);
457   } else     /* For starters, just keep the original algorithm. */
458   return Coll_alltoallv_ring::alltoallv(sbuf, scounts, sdisps, sdtype,
459       rbuf, rcounts, rdisps,rdtype,
460       comm);
461 }
462
463
464 int Coll_barrier_mvapich2::barrier(MPI_Comm  comm)
465 {
466   return Coll_barrier_mvapich2_pair::barrier(comm);
467 }
468
469
470
471
472 int Coll_bcast_mvapich2::bcast(void *buffer,
473     int count,
474     MPI_Datatype datatype,
475     int root, MPI_Comm comm)
476 {
477     int mpi_errno = MPI_SUCCESS;
478     int comm_size/*, rank*/;
479     int two_level_bcast = 1;
480     long nbytes = 0;
481     int range = 0;
482     int range_threshold = 0;
483     int range_threshold_intra = 0;
484     int is_homogeneous, is_contig;
485     MPI_Aint type_size;
486     //, position;
487     void *tmp_buf = NULL;
488     MPI_Comm shmem_comm;
489     //MPID_Datatype *dtp;
490
491     if (count == 0)
492         return MPI_SUCCESS;
493     if(comm->get_leaders_comm()==MPI_COMM_NULL){
494       comm->init_smp();
495     }
496     if (not mv2_bcast_thresholds_table)
497       init_mv2_bcast_tables_stampede();
498     comm_size = comm->size();
499     //rank = comm->rank();
500
501     is_contig=1;
502 /*    if (HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN)*/
503 /*        is_contig = 1;*/
504 /*    else {*/
505 /*        MPID_Datatype_get_ptr(datatype, dtp);*/
506 /*        is_contig = dtp->is_contig;*/
507 /*    }*/
508
509     is_homogeneous = 1;
510
511     /* MPI_Type_size() might not give the accurate size of the packed
512      * datatype for heterogeneous systems (because of padding, encoding,
513      * etc). On the other hand, MPI_Pack_size() can become very
514      * expensive, depending on the implementation, especially for
515      * heterogeneous systems. We want to use MPI_Type_size() wherever
516      * possible, and MPI_Pack_size() in other places.
517      */
518     //if (is_homogeneous) {
519         type_size=datatype->size();
520
521    /* } else {
522         MPIR_Pack_size_impl(1, datatype, &type_size);
523     }*/
524     nbytes =  (count) * (type_size);
525
526     /* Search for the corresponding system size inside the tuning table */
527     while ((range < (mv2_size_bcast_tuning_table - 1)) &&
528            (comm_size > mv2_bcast_thresholds_table[range].numproc)) {
529         range++;
530     }
531     /* Search for corresponding inter-leader function */
532     while ((range_threshold < (mv2_bcast_thresholds_table[range].size_inter_table - 1))
533            && (nbytes >
534                mv2_bcast_thresholds_table[range].inter_leader[range_threshold].max)
535            && (mv2_bcast_thresholds_table[range].inter_leader[range_threshold].max != -1)) {
536         range_threshold++;
537     }
538
539     /* Search for corresponding intra-node function */
540     while ((range_threshold_intra <
541             (mv2_bcast_thresholds_table[range].size_intra_table - 1))
542            && (nbytes >
543                mv2_bcast_thresholds_table[range].intra_node[range_threshold_intra].max)
544            && (mv2_bcast_thresholds_table[range].intra_node[range_threshold_intra].max !=
545                -1)) {
546         range_threshold_intra++;
547     }
548
549     MV2_Bcast_function =
550         mv2_bcast_thresholds_table[range].inter_leader[range_threshold].
551         MV2_pt_Bcast_function;
552
553     MV2_Bcast_intra_node_function =
554         mv2_bcast_thresholds_table[range].
555         intra_node[range_threshold_intra].MV2_pt_Bcast_function;
556
557 /*    if (mv2_user_bcast_intra == NULL && */
558 /*            MV2_Bcast_intra_node_function == &MPIR_Knomial_Bcast_intra_node_MV2) {*/
559 /*            MV2_Bcast_intra_node_function = &MPIR_Shmem_Bcast_MV2;*/
560 /*    }*/
561
562     if (mv2_bcast_thresholds_table[range].inter_leader[range_threshold].
563         zcpy_pipelined_knomial_factor != -1) {
564         zcpy_knomial_factor =
565             mv2_bcast_thresholds_table[range].inter_leader[range_threshold].
566             zcpy_pipelined_knomial_factor;
567     }
568
569     if (mv2_pipelined_zcpy_knomial_factor != -1) {
570         zcpy_knomial_factor = mv2_pipelined_zcpy_knomial_factor;
571     }
572
573     if(MV2_Bcast_intra_node_function == NULL) {
574         /* if tuning table do not have any intra selection, set func pointer to
575         ** default one for mcast intra node */
576         MV2_Bcast_intra_node_function = &MPIR_Shmem_Bcast_MV2;
577     }
578
579     /* Set value of pipeline segment size */
580     bcast_segment_size = mv2_bcast_thresholds_table[range].bcast_segment_size;
581
582     /* Set value of inter node knomial factor */
583     mv2_inter_node_knomial_factor = mv2_bcast_thresholds_table[range].inter_node_knomial_factor;
584
585     /* Set value of intra node knomial factor */
586     mv2_intra_node_knomial_factor = mv2_bcast_thresholds_table[range].intra_node_knomial_factor;
587
588     /* Check if we will use a two level algorithm or not */
589     two_level_bcast =
590 #if defined(_MCST_SUPPORT_)
591         mv2_bcast_thresholds_table[range].is_two_level_bcast[range_threshold]
592         || comm->ch.is_mcast_ok;
593 #else
594         mv2_bcast_thresholds_table[range].is_two_level_bcast[range_threshold];
595 #endif
596      if (two_level_bcast == 1) {
597        if (not is_contig || not is_homogeneous) {
598          tmp_buf = (void*)smpi_get_tmp_sendbuffer(nbytes);
599
600          /*            position = 0;*/
601          /*            if (rank == root) {*/
602          /*                mpi_errno =*/
603          /*                    MPIR_Pack_impl(buffer, count, datatype, tmp_buf, nbytes, &position);*/
604          /*                if (mpi_errno)*/
605          /*                    MPIU_ERR_POP(mpi_errno);*/
606          /*            }*/
607         }
608 #ifdef CHANNEL_MRAIL_GEN2
609         if ((mv2_enable_zcpy_bcast == 1) &&
610               (&MPIR_Pipelined_Bcast_Zcpy_MV2 == MV2_Bcast_function)) {
611           if (not is_contig || not is_homogeneous) {
612             mpi_errno = MPIR_Pipelined_Bcast_Zcpy_MV2(tmp_buf, nbytes, MPI_BYTE, root, comm);
613             } else {
614                 mpi_errno = MPIR_Pipelined_Bcast_Zcpy_MV2(buffer, count, datatype,
615                                                  root, comm);
616             }
617         } else
618 #endif /* defined(CHANNEL_MRAIL_GEN2) */
619         {
620             shmem_comm = comm->get_intra_comm();
621             if (not is_contig || not is_homogeneous) {
622               MPIR_Bcast_tune_inter_node_helper_MV2(tmp_buf, nbytes, MPI_BYTE, root, comm);
623             } else {
624               MPIR_Bcast_tune_inter_node_helper_MV2(buffer, count, datatype, root, comm);
625             }
626
627             /* We are now done with the inter-node phase */
628
629
630                     root = INTRA_NODE_ROOT;
631
632                     if (not is_contig || not is_homogeneous) {
633                       mpi_errno = MV2_Bcast_intra_node_function(tmp_buf, nbytes, MPI_BYTE, root, shmem_comm);
634                 } else {
635                     mpi_errno = MV2_Bcast_intra_node_function(buffer, count,
636                                                               datatype, root, shmem_comm);
637
638                 }
639         }
640         /*        if (not is_contig || not is_homogeneous) {*/
641         /*            if (rank != root) {*/
642         /*                position = 0;*/
643         /*                mpi_errno = MPIR_Unpack_impl(tmp_buf, nbytes, &position, buffer,*/
644         /*                                             count, datatype);*/
645         /*            }*/
646         /*        }*/
647     } else {
648         /* We use Knomial for intra node */
649         MV2_Bcast_intra_node_function = &MPIR_Knomial_Bcast_intra_node_MV2;
650 /*        if (mv2_enable_shmem_bcast == 0) {*/
651             /* Fall back to non-tuned version */
652 /*            MPIR_Bcast_intra_MV2(buffer, count, datatype, root, comm);*/
653 /*        } else {*/
654             mpi_errno = MV2_Bcast_function(buffer, count, datatype, root,
655                                            comm);
656
657 /*        }*/
658     }
659
660
661     return mpi_errno;
662
663 }
664
665
666
667 int Coll_reduce_mvapich2::reduce( void *sendbuf,
668     void *recvbuf,
669     int count,
670     MPI_Datatype datatype,
671     MPI_Op op, int root, MPI_Comm comm)
672 {
673   if(mv2_reduce_thresholds_table == NULL)
674     init_mv2_reduce_tables_stampede();
675
676   int mpi_errno = MPI_SUCCESS;
677   int range = 0;
678   int range_threshold = 0;
679   int range_intra_threshold = 0;
680   int is_commutative, pof2;
681   int comm_size = 0;
682   long nbytes = 0;
683   int sendtype_size;
684   int is_two_level = 0;
685
686   comm_size = comm->size();
687   sendtype_size=datatype->size();
688   nbytes = count * sendtype_size;
689
690   if (count == 0)
691     return MPI_SUCCESS;
692
693   is_commutative = (op==MPI_OP_NULL || op->is_commutative());
694
695   /* find nearest power-of-two less than or equal to comm_size */
696   for( pof2 = 1; pof2 <= comm_size; pof2 <<= 1 );
697   pof2 >>=1;
698
699
700   /* Search for the corresponding system size inside the tuning table */
701   while ((range < (mv2_size_reduce_tuning_table - 1)) &&
702       (comm_size > mv2_reduce_thresholds_table[range].numproc)) {
703       range++;
704   }
705   /* Search for corresponding inter-leader function */
706   while ((range_threshold < (mv2_reduce_thresholds_table[range].size_inter_table - 1))
707       && (nbytes >
708   mv2_reduce_thresholds_table[range].inter_leader[range_threshold].max)
709   && (mv2_reduce_thresholds_table[range].inter_leader[range_threshold].max !=
710       -1)) {
711       range_threshold++;
712   }
713
714   /* Search for corresponding intra node function */
715   while ((range_intra_threshold < (mv2_reduce_thresholds_table[range].size_intra_table - 1))
716       && (nbytes >
717   mv2_reduce_thresholds_table[range].intra_node[range_intra_threshold].max)
718   && (mv2_reduce_thresholds_table[range].intra_node[range_intra_threshold].max !=
719       -1)) {
720       range_intra_threshold++;
721   }
722
723   /* Set intra-node function pt for reduce_two_level */
724   MV2_Reduce_intra_function =
725       mv2_reduce_thresholds_table[range].intra_node[range_intra_threshold].
726       MV2_pt_Reduce_function;
727   /* Set inter-leader pt */
728   MV2_Reduce_function =
729       mv2_reduce_thresholds_table[range].inter_leader[range_threshold].
730       MV2_pt_Reduce_function;
731
732   if(mv2_reduce_intra_knomial_factor<0)
733     {
734       mv2_reduce_intra_knomial_factor = mv2_reduce_thresholds_table[range].intra_k_degree;
735     }
736   if(mv2_reduce_inter_knomial_factor<0)
737     {
738       mv2_reduce_inter_knomial_factor = mv2_reduce_thresholds_table[range].inter_k_degree;
739     }
740   if(mv2_reduce_thresholds_table[range].is_two_level_reduce[range_threshold] == 1){
741       is_two_level = 1;
742   }
743   /* We call Reduce function */
744   if(is_two_level == 1)
745     {
746        if (is_commutative == 1) {
747          if(comm->get_leaders_comm()==MPI_COMM_NULL){
748            comm->init_smp();
749          }
750          mpi_errno = MPIR_Reduce_two_level_helper_MV2(sendbuf, recvbuf, count,
751                                            datatype, op, root, comm);
752         } else {
753       mpi_errno = MPIR_Reduce_binomial_MV2(sendbuf, recvbuf, count,
754           datatype, op, root, comm);
755       }
756     } else if(MV2_Reduce_function == &MPIR_Reduce_inter_knomial_wrapper_MV2 ){
757         if(is_commutative ==1)
758           {
759             mpi_errno = MV2_Reduce_function(sendbuf, recvbuf, count,
760                 datatype, op, root, comm);
761           } else {
762               mpi_errno = MPIR_Reduce_binomial_MV2(sendbuf, recvbuf, count,
763                   datatype, op, root, comm);
764           }
765     } else if(MV2_Reduce_function == &MPIR_Reduce_redscat_gather_MV2){
766         if (/*(HANDLE_GET_KIND(op) == HANDLE_KIND_BUILTIN) &&*/ (count >= pof2))
767           {
768             mpi_errno = MV2_Reduce_function(sendbuf, recvbuf, count,
769                 datatype, op, root, comm);
770           } else {
771               mpi_errno = MPIR_Reduce_binomial_MV2(sendbuf, recvbuf, count,
772                   datatype, op, root, comm);
773           }
774     } else {
775         mpi_errno = MV2_Reduce_function(sendbuf, recvbuf, count,
776             datatype, op, root, comm);
777     }
778
779
780   return mpi_errno;
781
782 }
783
784
785 int Coll_reduce_scatter_mvapich2::reduce_scatter(void *sendbuf, void *recvbuf, int *recvcnts,
786     MPI_Datatype datatype, MPI_Op op,
787     MPI_Comm comm)
788 {
789   int mpi_errno = MPI_SUCCESS;
790   int i = 0, comm_size = comm->size(), total_count = 0, type_size =
791       0, nbytes = 0;
792   int is_commutative = 0;
793   int* disps          = new int[comm_size];
794
795   if(mv2_red_scat_thresholds_table==NULL)
796     init_mv2_reduce_scatter_tables_stampede();
797
798   is_commutative=(op==MPI_OP_NULL || op->is_commutative());
799   for (i = 0; i < comm_size; i++) {
800       disps[i] = total_count;
801       total_count += recvcnts[i];
802   }
803
804   type_size=datatype->size();
805   nbytes = total_count * type_size;
806
807   if (is_commutative) {
808     int range           = 0;
809     int range_threshold = 0;
810
811       /* Search for the corresponding system size inside the tuning table */
812       while ((range < (mv2_size_red_scat_tuning_table - 1)) &&
813           (comm_size > mv2_red_scat_thresholds_table[range].numproc)) {
814           range++;
815       }
816       /* Search for corresponding inter-leader function */
817       while ((range_threshold < (mv2_red_scat_thresholds_table[range].size_inter_table - 1))
818           && (nbytes >
819       mv2_red_scat_thresholds_table[range].inter_leader[range_threshold].max)
820       && (mv2_red_scat_thresholds_table[range].inter_leader[range_threshold].max !=
821           -1)) {
822           range_threshold++;
823       }
824
825       /* Set inter-leader pt */
826       MV2_Red_scat_function =
827           mv2_red_scat_thresholds_table[range].inter_leader[range_threshold].
828           MV2_pt_Red_scat_function;
829
830       mpi_errno = MV2_Red_scat_function(sendbuf, recvbuf,
831           recvcnts, datatype,
832           op, comm);
833   } else {
834       int is_block_regular = 1;
835       for (i = 0; i < (comm_size - 1); ++i) {
836           if (recvcnts[i] != recvcnts[i+1]) {
837               is_block_regular = 0;
838               break;
839           }
840       }
841       int pof2 = 1;
842       while (pof2 < comm_size) pof2 <<= 1;
843       if (pof2 == comm_size && is_block_regular) {
844           /* noncommutative, pof2 size, and block regular */
845           MPIR_Reduce_scatter_non_comm_MV2(sendbuf, recvbuf,
846               recvcnts, datatype,
847               op, comm);
848       }
849       mpi_errno =  Coll_reduce_scatter_mpich_rdb::reduce_scatter(sendbuf, recvbuf,
850           recvcnts, datatype,
851           op, comm);
852   }
853   delete[] disps;
854   return mpi_errno;
855
856 }
857
858
859
860 int Coll_scatter_mvapich2::scatter(void *sendbuf,
861     int sendcnt,
862     MPI_Datatype sendtype,
863     void *recvbuf,
864     int recvcnt,
865     MPI_Datatype recvtype,
866     int root, MPI_Comm comm)
867 {
868   int range = 0, range_threshold = 0, range_threshold_intra = 0;
869   int mpi_errno = MPI_SUCCESS;
870   //   int mpi_errno_ret = MPI_SUCCESS;
871   int rank, nbytes, comm_size;
872   int partial_sub_ok = 0;
873   int conf_index = 0;
874      MPI_Comm shmem_comm;
875   //    MPID_Comm *shmem_commptr=NULL;
876   if(mv2_scatter_thresholds_table==NULL)
877     init_mv2_scatter_tables_stampede();
878
879   if(comm->get_leaders_comm()==MPI_COMM_NULL){
880     comm->init_smp();
881   }
882
883   comm_size = comm->size();
884
885   rank = comm->rank();
886
887   if (rank == root) {
888     int sendtype_size = sendtype->size();
889     nbytes            = sendcnt * sendtype_size;
890   } else {
891     int recvtype_size = recvtype->size();
892     nbytes            = recvcnt * recvtype_size;
893   }
894
895     // check if safe to use partial subscription mode
896     if (comm->is_uniform()) {
897
898         shmem_comm = comm->get_intra_comm();
899         int local_size = shmem_comm->size();
900         int i          = 0;
901         if (mv2_scatter_table_ppn_conf[0] == -1) {
902             // Indicating user defined tuning
903             conf_index = 0;
904         }else{
905             do {
906                 if (local_size == mv2_scatter_table_ppn_conf[i]) {
907                     conf_index = i;
908                     partial_sub_ok = 1;
909                     break;
910                 }
911                 i++;
912             } while(i < mv2_scatter_num_ppn_conf);
913         }
914     }
915
916   if (partial_sub_ok != 1) {
917       conf_index = 0;
918   }
919
920   /* Search for the corresponding system size inside the tuning table */
921   while ((range < (mv2_size_scatter_tuning_table[conf_index] - 1)) &&
922       (comm_size > mv2_scatter_thresholds_table[conf_index][range].numproc)) {
923       range++;
924   }
925   /* Search for corresponding inter-leader function */
926   while ((range_threshold < (mv2_scatter_thresholds_table[conf_index][range].size_inter_table - 1))
927       && (nbytes >
928   mv2_scatter_thresholds_table[conf_index][range].inter_leader[range_threshold].max)
929   && (mv2_scatter_thresholds_table[conf_index][range].inter_leader[range_threshold].max != -1)) {
930       range_threshold++;
931   }
932
933   /* Search for corresponding intra-node function */
934   while ((range_threshold_intra <
935       (mv2_scatter_thresholds_table[conf_index][range].size_intra_table - 1))
936       && (nbytes >
937   mv2_scatter_thresholds_table[conf_index][range].intra_node[range_threshold_intra].max)
938   && (mv2_scatter_thresholds_table[conf_index][range].intra_node[range_threshold_intra].max !=
939       -1)) {
940       range_threshold_intra++;
941   }
942
943   MV2_Scatter_function = mv2_scatter_thresholds_table[conf_index][range].inter_leader[range_threshold]
944                                                                                       .MV2_pt_Scatter_function;
945
946   if(MV2_Scatter_function == &MPIR_Scatter_mcst_wrap_MV2) {
947 #if defined(_MCST_SUPPORT_)
948       if(comm->ch.is_mcast_ok == 1
949           && mv2_use_mcast_scatter == 1
950           && comm->ch.shmem_coll_ok == 1) {
951           MV2_Scatter_function = &MPIR_Scatter_mcst_MV2;
952       } else
953 #endif /*#if defined(_MCST_SUPPORT_) */
954         {
955           if(mv2_scatter_thresholds_table[conf_index][range].inter_leader[range_threshold + 1].
956               MV2_pt_Scatter_function != NULL) {
957               MV2_Scatter_function = mv2_scatter_thresholds_table[conf_index][range].inter_leader[range_threshold + 1]
958                                                                                                   .MV2_pt_Scatter_function;
959           } else {
960               /* Fallback! */
961               MV2_Scatter_function = &MPIR_Scatter_MV2_Binomial;
962           }
963         }
964   }
965
966   if( (MV2_Scatter_function == &MPIR_Scatter_MV2_two_level_Direct) ||
967       (MV2_Scatter_function == &MPIR_Scatter_MV2_two_level_Binomial)) {
968        if( comm->is_blocked()) {
969              MV2_Scatter_intra_function = mv2_scatter_thresholds_table[conf_index][range].intra_node[range_threshold_intra]
970                                 .MV2_pt_Scatter_function;
971
972              mpi_errno =
973                    MV2_Scatter_function(sendbuf, sendcnt, sendtype,
974                                         recvbuf, recvcnt, recvtype, root,
975                                         comm);
976          } else {
977       mpi_errno = MPIR_Scatter_MV2_Binomial(sendbuf, sendcnt, sendtype,
978           recvbuf, recvcnt, recvtype, root,
979           comm);
980
981       }
982   } else {
983       mpi_errno = MV2_Scatter_function(sendbuf, sendcnt, sendtype,
984           recvbuf, recvcnt, recvtype, root,
985           comm);
986   }
987   return (mpi_errno);
988 }
989
990 }
991 }
992
993 void smpi_coll_cleanup_mvapich2()
994 {
995   if (mv2_alltoall_thresholds_table)
996     delete[] mv2_alltoall_thresholds_table[0];
997   delete[] mv2_alltoall_thresholds_table;
998   delete[] mv2_size_alltoall_tuning_table;
999   delete[] mv2_alltoall_table_ppn_conf;
1000
1001   delete[] mv2_gather_thresholds_table;
1002   if (mv2_allgather_thresholds_table)
1003     delete[] mv2_allgather_thresholds_table[0];
1004   delete[] mv2_size_allgather_tuning_table;
1005   delete[] mv2_allgather_table_ppn_conf;
1006   delete[] mv2_allgather_thresholds_table;
1007
1008   delete[] mv2_allgatherv_thresholds_table;
1009   delete[] mv2_reduce_thresholds_table;
1010   delete[] mv2_red_scat_thresholds_table;
1011   delete[] mv2_allreduce_thresholds_table;
1012   delete[] mv2_bcast_thresholds_table;
1013   if (mv2_scatter_thresholds_table)
1014     delete[] mv2_scatter_thresholds_table[0];
1015   delete[] mv2_scatter_thresholds_table;
1016   delete[] mv2_size_scatter_tuning_table;
1017   delete[] mv2_scatter_table_ppn_conf;
1018 }