Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
change spmirun and smpicc to use bash instead of sh and smpi_mpi to use qsort
[simgrid.git] / src / smpi / smpi_mpi.c
1 #include "private.h"
2
3 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi, smpi, "Logging specific to SMPI (mpi)");
4
5 int SMPI_MPI_Init(int *argc, char ***argv)
6 {
7         smpi_mpi_init();
8         smpi_bench_begin();
9         return MPI_SUCCESS;
10 }
11
12 int SMPI_MPI_Finalize()
13 {
14         smpi_bench_end();
15         smpi_mpi_finalize();
16         return MPI_SUCCESS;
17 }
18
19 // right now this just exits the current node, should send abort signal to all
20 // hosts in the communicator;
21 int SMPI_MPI_Abort(MPI_Comm comm, int errorcode)
22 {
23         smpi_exit(errorcode);
24         return 0;
25 }
26
27 int SMPI_MPI_Comm_size(MPI_Comm comm, int *size)
28 {
29         int retval = MPI_SUCCESS;
30
31         smpi_bench_end();
32
33         if (NULL == comm) {
34                 retval = MPI_ERR_COMM;
35         } else if (NULL == size) {
36                 retval = MPI_ERR_ARG;
37         } else {
38                 *size = comm->size;
39         }
40
41         smpi_bench_begin();
42
43         return retval;
44 }
45
46 int SMPI_MPI_Comm_rank(MPI_Comm comm, int *rank)
47 {
48         int retval = MPI_SUCCESS;
49
50         smpi_bench_end();
51
52         if (NULL == comm) {
53                 retval = MPI_ERR_COMM;
54         } else if (NULL == rank) {
55                 retval = MPI_ERR_ARG;
56         } else {
57                 *rank = smpi_mpi_comm_rank(comm);
58         }
59
60         smpi_bench_begin();
61
62         return retval;
63 }
64
65 int SMPI_MPI_Type_size(MPI_Datatype datatype, size_t *size)
66 {
67         int retval = MPI_SUCCESS;
68
69         smpi_bench_end();
70
71         if (NULL == datatype) {
72                 retval = MPI_ERR_TYPE;
73         } else if (NULL == size) {
74                 retval = MPI_ERR_ARG;
75         } else {
76                 *size = datatype->size;
77         }
78
79         smpi_bench_begin();
80
81         return retval;
82 }
83
84 int SMPI_MPI_Barrier(MPI_Comm comm)
85 {
86         int retval = MPI_SUCCESS;
87
88         smpi_bench_end();
89
90         if (NULL == comm) {
91                 retval = MPI_ERR_COMM;
92         } else {
93                 retval = smpi_mpi_barrier(comm);
94         }
95
96         smpi_bench_begin();
97
98         return retval;
99 }
100
101 int SMPI_MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Request *request)
102 {
103         int retval = MPI_SUCCESS;
104
105         smpi_bench_end();
106
107         retval = smpi_create_request(buf, count, datatype, src, 0, tag, comm, request);
108         if (NULL != *request && MPI_SUCCESS == retval) {
109                 retval = smpi_mpi_irecv(*request);
110         }
111
112         smpi_bench_begin();
113
114         return retval;
115 }
116
117 int SMPI_MPI_Recv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Status *status)
118 {
119         int retval = MPI_SUCCESS;
120         smpi_mpi_request_t request;
121
122         smpi_bench_end();
123
124         retval = smpi_create_request(buf, count, datatype, src, 0, tag, comm, &request);
125         if (NULL != request && MPI_SUCCESS == retval) {
126                 retval = smpi_mpi_irecv(request);
127                 if (MPI_SUCCESS == retval) {
128                         retval = smpi_mpi_wait(request, status);
129                 }
130                 xbt_mallocator_release(smpi_global->request_mallocator, request);
131         }
132
133         smpi_bench_begin();
134
135         return retval;
136 }
137
138 int SMPI_MPI_Isend(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request *request)
139 {
140         int retval = MPI_SUCCESS;
141
142         smpi_bench_end();
143
144         retval = smpi_create_request(buf, count, datatype, 0, dst, tag, comm, request);
145         if (NULL != *request && MPI_SUCCESS == retval) {
146                 retval = smpi_mpi_isend(*request);
147         }
148
149         smpi_bench_begin();
150
151         return retval;
152 }
153
154 int SMPI_MPI_Send(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm)
155 {
156         int retval = MPI_SUCCESS;
157         smpi_mpi_request_t request;
158
159         smpi_bench_end();
160
161         retval = smpi_create_request(buf, count, datatype, 0, dst, tag, comm, &request);
162         if (NULL != request && MPI_SUCCESS == retval) {
163                 retval = smpi_mpi_isend(request);
164                 if (MPI_SUCCESS == retval) {
165                         smpi_mpi_wait(request, MPI_STATUS_IGNORE);
166                 }
167                 xbt_mallocator_release(smpi_global->request_mallocator, request);
168         }
169
170         smpi_bench_begin();
171
172         return retval;
173 }
174
175 int SMPI_MPI_Wait(MPI_Request *request, MPI_Status *status) {
176         return smpi_mpi_wait(*request, status);
177 }
178
179 int SMPI_MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) {
180
181         int retval = MPI_SUCCESS;
182         int rank;
183         smpi_mpi_request_t request;
184
185         smpi_bench_end();
186
187         rank = smpi_mpi_comm_rank(comm);
188
189         if (rank == root) {
190                 retval = smpi_create_request(buf, count, datatype, root, (root + 1) % comm->size, 0, comm, &request);
191                 request->forward = comm->size - 1;
192                 smpi_mpi_isend(request);
193         } else {
194                 retval = smpi_create_request(buf, count, datatype, MPI_ANY_SOURCE, rank, 0, comm, &request);
195                 smpi_mpi_irecv(request);
196         }
197
198         smpi_mpi_wait(request, MPI_STATUS_IGNORE);
199         xbt_mallocator_release(smpi_global->request_mallocator, request);
200
201         smpi_bench_begin();
202
203         return retval;
204 }
205
206 // FIXME: should be in utilities
207 int smpi_compare_rankkeys(const void *a, const void *b);
208 int smpi_compare_rankkeys(const void *a, const void *b) {
209     int *x = (int *)a;
210     int *y = (int *)b;
211
212     if (x[1] < y[1]) return -1;
213
214     if (x[1] == y[1]) {
215         if (x[0] < y[0]) return -1;
216         if (x[0] == y[0]) return 0;
217         return 1;
218     }
219
220     return 1;
221 }
222
223 // FIXME: needs to return null in event of MPI_UNDEFINED color...
224 // FIXME: seriously, this isn't pretty
225 int SMPI_MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *comm_out)
226 {
227         int retval = MPI_SUCCESS;
228
229         int index, rank;
230         smpi_mpi_request_t request;
231         int colorkey[2];
232         smpi_mpi_status_t status;
233
234         smpi_bench_end();
235
236         // FIXME: need to test parameters
237
238         index = smpi_host_index();
239         rank  = comm->index_to_rank_map[index];
240
241         if (0 == rank) {
242                 int colormap[comm->size];
243         int keymap[comm->size];
244         int rankkeymap[comm->size * 2];
245                 int i, j;
246                 smpi_mpi_communicator_t tempcomm = NULL;
247                 int colortmp;
248                 int keycount;
249                 int indextmp;
250
251                 colormap[0] = color;
252         keymap[0]   = key;
253
254                 // FIXME: use scatter/gather or similar instead of individual comms
255                 for (i = 1; i < comm->size; i++) {
256                         retval = smpi_create_request(colorkey, 2, MPI_INT, MPI_ANY_SOURCE,
257                     rank, MPI_ANY_TAG, comm, &request);
258                         smpi_mpi_irecv(request);
259                         smpi_mpi_wait(request, &status);
260                         colormap[status.MPI_SOURCE] = colorkey[0];
261                         keymap[status.MPI_SOURCE]   = colorkey[1];
262                         xbt_mallocator_release(smpi_global->request_mallocator, request);
263                 }
264
265                 for (i = 0; i < comm->size; i++) {
266                         if (-1 == colormap[i]) {
267                                 continue;
268                         }
269                         colortmp = colormap[i];
270                         keycount = 0;
271                         for (j = i; j < comm->size; j++) {
272                                 if(colortmp == colormap[j]) {
273                                         colormap[j] = -1;
274                                         rankkeymap[keycount * 2]     = j;
275                                         rankkeymap[keycount * 2 + 1] = keymap[j];
276                                         keycount++;
277                                 }
278                         }
279             qsort(rankkeymap, keycount, sizeof(int) * 2, &smpi_compare_rankkeys);
280                         tempcomm                    = xbt_new(s_smpi_mpi_communicator_t, 1);
281                         tempcomm->barrier_count     = 0;
282                         tempcomm->size              = keycount;
283                         tempcomm->barrier_mutex     = SIMIX_mutex_init();
284                         tempcomm->barrier_cond      = SIMIX_cond_init();
285                         tempcomm->rank_to_index_map = xbt_new(int, keycount);
286                         tempcomm->index_to_rank_map = xbt_new(int, smpi_global->host_count);
287                         for (j = 0; j < smpi_global->host_count; j++) {
288                                 tempcomm->index_to_rank_map[j] = -1;
289                         }
290                         for (j = 0; j < keycount; j++) {
291                                 indextmp = comm->rank_to_index_map[rankkeymap[j*2]];
292                                 tempcomm->rank_to_index_map[j]        = indextmp;
293                                 tempcomm->index_to_rank_map[indextmp] = j;
294                         }
295                         for (j = 0; j < keycount; j++) {
296                                 if (rankkeymap[j*2]) {
297                                         retval = smpi_create_request(&j, 1, MPI_INT, 0,
298                         rankkeymap[j*2], 0, comm, &request);
299                                         request->data = tempcomm;
300                                         smpi_mpi_isend(request);
301                                         smpi_mpi_wait(request, &status);
302                                         xbt_mallocator_release(smpi_global->request_mallocator, request);
303                                 } else {
304                                         *comm_out = tempcomm;
305                                 }
306                         }
307                 }
308         } else {
309                 colorkey[0] = color;
310                 colorkey[1] = key;
311                 retval = smpi_create_request(colorkey, 2, MPI_INT, rank, 0, 0, comm, &request);
312                 smpi_mpi_isend(request);
313                 smpi_mpi_wait(request, &status);
314                 xbt_mallocator_release(smpi_global->request_mallocator, request);
315                 retval = smpi_create_request(colorkey, 1, MPI_INT, 0, rank, 0, comm, &request);
316                 smpi_mpi_irecv(request);
317                 smpi_mpi_wait(request, &status);
318                 *comm_out = request->data;
319         }
320
321         smpi_bench_begin();
322
323         return retval;
324 }