Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
have smp-aware algorithms use number of cores on the node as basis for their computat...
[simgrid.git] / src / smpi / colls / bcast-SMP-binomial.c
1 #include "colls_private.h"
2 #ifndef NUM_CORE
3 #define NUM_CORE 8
4 #endif
5
6 int smpi_coll_tuned_bcast_SMP_binomial(void *buf, int count,
7                                        MPI_Datatype datatype, int root,
8                                        MPI_Comm comm)
9 {
10   int mask = 1;
11   int size;
12   int rank;
13   MPI_Status status;
14   int tag = COLL_TAG_BCAST;
15
16   size = smpi_comm_size(comm);
17   rank = smpi_comm_rank(comm);
18
19   int num_core = simcall_host_get_core(SIMIX_host_self());
20   // do we use the default one or the number of cores in the platform ?
21   // if the number of cores is one, the platform may be simulated with 1 node = 1 core
22   if (num_core == 1) num_core = NUM_CORE;
23
24   if(size%num_core)
25     THROWF(arg_error,0, "bcast SMP binomial can't be used with non multiple of NUM_CORE=%d number of processes ! ",num_core);
26
27   int to_intra, to_inter;
28   int from_intra, from_inter;
29   int inter_rank = rank / num_core;
30   int inter_size = (size - 1) / num_core + 1;
31   int intra_rank = rank % num_core;
32   int intra_size = num_core;
33   if (((rank / num_core) * num_core) == ((size / num_core) * num_core))
34     intra_size = size - (rank / num_core) * num_core;
35
36   // if root is not zero send to rank zero first
37   if (root != 0) {
38     if (rank == root)
39       smpi_mpi_send(buf, count, datatype, 0, tag, comm);
40     else if (rank == 0)
41       smpi_mpi_recv(buf, count, datatype, root, tag, comm, &status);
42   }
43   //FIRST STEP node 0 send to every root-of-each-SMP with binomial tree
44
45   //printf("node %d inter_rank = %d, inter_size = %d\n",rank,inter_rank, inter_size);
46
47   if (intra_rank == 0) {
48     mask = 1;
49     while (mask < inter_size) {
50       if (inter_rank & mask) {
51         from_inter = (inter_rank - mask) * num_core;
52         //printf("Node %d recv from node %d when mask is %d\n", rank, from_inter, mask);
53         smpi_mpi_recv(buf, count, datatype, from_inter, tag, comm, &status);
54         break;
55       }
56       mask <<= 1;
57     }
58
59     mask >>= 1;
60     //printf("My rank = %d my mask = %d\n", rank,mask);
61
62     while (mask > 0) {
63       if (inter_rank < inter_size) {
64         to_inter = (inter_rank + mask) * num_core;
65         if (to_inter < size) {
66           //printf("Node %d send to node %d when mask is %d\n", rank, to_inter, mask);
67           smpi_mpi_send(buf, count, datatype, to_inter, tag, comm);
68         }
69       }
70       mask >>= 1;
71     }
72   }
73   // SECOND STEP every root-of-each-SMP send to all children with binomial tree
74   // base is a rank of root-of-each-SMP
75   int base = (rank / num_core) * num_core;
76   mask = 1;
77   while (mask < intra_size) {
78     if (intra_rank & mask) {
79       from_intra = base + (intra_rank - mask);
80       //printf("Node %d recv from node %d when mask is %d\n", rank, from_inter, mask);
81       smpi_mpi_recv(buf, count, datatype, from_intra, tag, comm, &status);
82       break;
83     }
84     mask <<= 1;
85   }
86
87   mask >>= 1;
88
89   //printf("My rank = %d my mask = %d\n", rank,mask);
90
91   while (mask > 0) {
92     if (intra_rank < intra_size) {
93       to_intra = base + (intra_rank + mask);
94       if (to_intra < size) {
95         //printf("Node %d send to node %d when mask is %d\n", rank, to_inter, mask);
96         smpi_mpi_send(buf, count, datatype, to_intra, tag, comm);
97       }
98     }
99     mask >>= 1;
100   }
101
102   return MPI_SUCCESS;
103 }