Logo AND Algorithmique Numérique Distribuée

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