Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
6053e49c7a02c1ea8ad88673632eff3155ae94c0
[simgrid.git] / src / smpi / colls / bcast-SMP-binomial.cpp
1 /* Copyright (c) 2013-2014. 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.h"
8
9 int smpi_coll_tuned_bcast_SMP_binomial(void *buf, int count,
10                                        MPI_Datatype datatype, int root,
11                                        MPI_Comm comm)
12 {
13   int mask = 1;
14   int size;
15   int rank;
16   MPI_Status status;
17   int tag = COLL_TAG_BCAST;
18
19   size = smpi_comm_size(comm);
20   rank = smpi_comm_rank(comm);
21
22   if(smpi_comm_get_leaders_comm(comm)==MPI_COMM_NULL){
23     smpi_comm_init_smp(comm);
24   }
25   int num_core=1;
26   if (smpi_comm_is_uniform(comm)){
27     num_core = smpi_comm_size(smpi_comm_get_intra_comm(comm));
28   }else{
29     //implementation buggy in this case
30     return smpi_coll_tuned_bcast_mpich( buf , count, datatype,
31               root, comm);
32   }
33
34   int to_intra, to_inter;
35   int from_intra, from_inter;
36   int inter_rank = rank / num_core;
37   int inter_size = (size - 1) / num_core + 1;
38   int intra_rank = rank % num_core;
39   int intra_size = num_core;
40   if (((rank / num_core) * num_core) == ((size / num_core) * num_core))
41     intra_size = size - (rank / num_core) * num_core;
42
43   // if root is not zero send to rank zero first
44   if (root != 0) {
45     if (rank == root)
46       smpi_mpi_send(buf, count, datatype, 0, tag, comm);
47     else if (rank == 0)
48       smpi_mpi_recv(buf, count, datatype, root, tag, comm, &status);
49   }
50   //FIRST STEP node 0 send to every root-of-each-SMP with binomial tree
51
52   //printf("node %d inter_rank = %d, inter_size = %d\n",rank,inter_rank, inter_size);
53
54   if (intra_rank == 0) {
55     mask = 1;
56     while (mask < inter_size) {
57       if (inter_rank & mask) {
58         from_inter = (inter_rank - mask) * num_core;
59         //printf("Node %d recv from node %d when mask is %d\n", rank, from_inter, mask);
60         smpi_mpi_recv(buf, count, datatype, from_inter, tag, comm, &status);
61         break;
62       }
63       mask <<= 1;
64     }
65
66     mask >>= 1;
67     //printf("My rank = %d my mask = %d\n", rank,mask);
68
69     while (mask > 0) {
70       if (inter_rank < inter_size) {
71         to_inter = (inter_rank + mask) * num_core;
72         if (to_inter < size) {
73           //printf("Node %d send to node %d when mask is %d\n", rank, to_inter, mask);
74           smpi_mpi_send(buf, count, datatype, to_inter, tag, comm);
75         }
76       }
77       mask >>= 1;
78     }
79   }
80   // SECOND STEP every root-of-each-SMP send to all children with binomial tree
81   // base is a rank of root-of-each-SMP
82   int base = (rank / num_core) * num_core;
83   mask = 1;
84   while (mask < intra_size) {
85     if (intra_rank & mask) {
86       from_intra = base + (intra_rank - mask);
87       //printf("Node %d recv from node %d when mask is %d\n", rank, from_inter, mask);
88       smpi_mpi_recv(buf, count, datatype, from_intra, tag, comm, &status);
89       break;
90     }
91     mask <<= 1;
92   }
93
94   mask >>= 1;
95
96   //printf("My rank = %d my mask = %d\n", rank,mask);
97
98   while (mask > 0) {
99     if (intra_rank < intra_size) {
100       to_intra = base + (intra_rank + mask);
101       if (to_intra < size) {
102         //printf("Node %d send to node %d when mask is %d\n", rank, to_inter, mask);
103         smpi_mpi_send(buf, count, datatype, to_intra, tag, comm);
104       }
105     }
106     mask >>= 1;
107   }
108
109   return MPI_SUCCESS;
110 }