Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
[simgrid.git] / src / smpi / colls / bcast / bcast-SMP-binomial.cpp
1 /* Copyright (c) 2013-2017. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "../colls_private.hpp"
8 namespace simgrid{
9 namespace smpi{
10 int Coll_bcast_SMP_binomial::bcast(void *buf, int count,
11                                        MPI_Datatype datatype, int root,
12                                        MPI_Comm comm)
13 {
14   int mask = 1;
15   int size;
16   int rank;
17   MPI_Status status;
18   int tag = COLL_TAG_BCAST;
19
20   size = comm->size();
21   rank = comm->rank();
22
23   if(comm->get_leaders_comm()==MPI_COMM_NULL){
24     comm->init_smp();
25   }
26   int num_core=1;
27   if (comm->is_uniform()){
28     num_core = comm->get_intra_comm()->size();
29   }else{
30     //implementation buggy in this case
31     return Coll_bcast_mpich::bcast( buf , count, datatype,
32               root, comm);
33   }
34
35   int to_intra, to_inter;
36   int from_intra, from_inter;
37   int inter_rank = rank / num_core;
38   int inter_size = (size - 1) / num_core + 1;
39   int intra_rank = rank % num_core;
40   int intra_size = num_core;
41   if (((rank / num_core) * num_core) == ((size / num_core) * num_core))
42     intra_size = size - (rank / num_core) * num_core;
43
44   // if root is not zero send to rank zero first
45   if (root != 0) {
46     if (rank == root)
47       Request::send(buf, count, datatype, 0, tag, comm);
48     else if (rank == 0)
49       Request::recv(buf, count, datatype, root, tag, comm, &status);
50   }
51   //FIRST STEP node 0 send to every root-of-each-SMP with binomial tree
52
53   //printf("node %d inter_rank = %d, inter_size = %d\n",rank,inter_rank, inter_size);
54
55   if (intra_rank == 0) {
56     mask = 1;
57     while (mask < inter_size) {
58       if (inter_rank & mask) {
59         from_inter = (inter_rank - mask) * num_core;
60         //printf("Node %d recv from node %d when mask is %d\n", rank, from_inter, mask);
61         Request::recv(buf, count, datatype, from_inter, tag, comm, &status);
62         break;
63       }
64       mask <<= 1;
65     }
66
67     mask >>= 1;
68     //printf("My rank = %d my mask = %d\n", rank,mask);
69
70     while (mask > 0) {
71       if (inter_rank < inter_size) {
72         to_inter = (inter_rank + mask) * num_core;
73         if (to_inter < size) {
74           //printf("Node %d send to node %d when mask is %d\n", rank, to_inter, mask);
75           Request::send(buf, count, datatype, to_inter, tag, comm);
76         }
77       }
78       mask >>= 1;
79     }
80   }
81   // SECOND STEP every root-of-each-SMP send to all children with binomial tree
82   // base is a rank of root-of-each-SMP
83   int base = (rank / num_core) * num_core;
84   mask = 1;
85   while (mask < intra_size) {
86     if (intra_rank & mask) {
87       from_intra = base + (intra_rank - mask);
88       //printf("Node %d recv from node %d when mask is %d\n", rank, from_inter, mask);
89       Request::recv(buf, count, datatype, from_intra, tag, comm, &status);
90       break;
91     }
92     mask <<= 1;
93   }
94
95   mask >>= 1;
96
97   //printf("My rank = %d my mask = %d\n", rank,mask);
98
99   while (mask > 0) {
100     if (intra_rank < intra_size) {
101       to_intra = base + (intra_rank + mask);
102       if (to_intra < size) {
103         //printf("Node %d send to node %d when mask is %d\n", rank, to_inter, mask);
104         Request::send(buf, count, datatype, to_intra, tag, comm);
105       }
106     }
107     mask >>= 1;
108   }
109
110   return MPI_SUCCESS;
111 }
112
113 }
114 }