Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
(painfully) constify colls.
[simgrid.git] / src / smpi / colls / smpi_nbc_impl.cpp
1 /* Asynchronous parts of the basic collective algorithms, meant to be used both for the naive default implementation, but also for non blocking collectives */
2
3 /* Copyright (c) 2009-2019. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "colls_private.hpp"
9 #include "src/smpi/include/smpi_actor.hpp"
10
11 namespace simgrid{
12 namespace smpi{
13
14
15 int Colls::ibarrier(MPI_Comm comm, MPI_Request* request)
16 {
17   int size = comm->size();
18   int rank = comm->rank();
19   (*request) = new Request( nullptr, 0, MPI_BYTE,
20                          rank,rank, COLL_TAG_BARRIER, comm, MPI_REQ_PERSISTENT);
21   if (rank > 0) {
22     MPI_Request* requests = new MPI_Request[2];
23     requests[0] = Request::isend (nullptr, 0, MPI_BYTE, 0,
24                              COLL_TAG_BARRIER,
25                              comm);
26     requests[1] = Request::irecv (nullptr, 0, MPI_BYTE, 0,
27                              COLL_TAG_BARRIER,
28                              comm);
29     (*request)->set_nbc_requests(requests, 2);
30   }
31   else {
32     MPI_Request* requests = new MPI_Request[(size - 1) * 2];
33     for (int i = 1; i < 2 * size - 1; i += 2) {
34       requests[i - 1] = Request::irecv(nullptr, 0, MPI_BYTE, MPI_ANY_SOURCE, COLL_TAG_BARRIER, comm);
35       requests[i]     = Request::isend(nullptr, 0, MPI_BYTE, (i + 1) / 2, COLL_TAG_BARRIER, comm);
36     }
37     (*request)->set_nbc_requests(requests, 2*(size-1));
38   }
39   return MPI_SUCCESS;
40 }
41
42 int Colls::ibcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm, MPI_Request* request)
43 {
44   int size = comm->size();
45   int rank = comm->rank();
46   (*request) = new Request( nullptr, 0, MPI_BYTE,
47                          rank,rank, COLL_TAG_BCAST, comm, MPI_REQ_PERSISTENT);
48   if (rank != root) {
49     MPI_Request* requests = new MPI_Request[1];
50     requests[0] = Request::irecv (buf, count, datatype, root,
51                              COLL_TAG_BCAST,
52                              comm);
53     (*request)->set_nbc_requests(requests, 1);
54   }
55   else {
56     MPI_Request* requests = new MPI_Request[size - 1];
57     int n = 0;
58     for (int i = 0; i < size; i++) {
59       if(i!=root){
60         requests[n] = Request::isend(buf, count, datatype, i,
61                                  COLL_TAG_BCAST,
62                                  comm
63                                  );
64         n++;
65       }
66     }
67     (*request)->set_nbc_requests(requests, size-1);
68   }
69   return MPI_SUCCESS;
70 }
71
72 int Colls::iallgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
73                         void *recvbuf,int recvcount, MPI_Datatype recvtype, MPI_Comm comm, MPI_Request* request)
74 {
75
76   const int system_tag = COLL_TAG_ALLGATHER;
77   MPI_Aint lb = 0;
78   MPI_Aint recvext = 0;
79
80   int rank = comm->rank();
81   int size = comm->size();
82   (*request) = new Request( nullptr, 0, MPI_BYTE,
83                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
84   // FIXME: check for errors
85   recvtype->extent(&lb, &recvext);
86   // Local copy from self
87   Datatype::copy(sendbuf, sendcount, sendtype, static_cast<char *>(recvbuf) + rank * recvcount * recvext, recvcount,
88                      recvtype);
89   // Send/Recv buffers to/from others;
90   MPI_Request* requests = new MPI_Request[2 * (size - 1)];
91   int index = 0;
92   for (int other = 0; other < size; other++) {
93     if(other != rank) {
94       requests[index] = Request::isend_init(sendbuf, sendcount, sendtype, other, system_tag,comm);
95       index++;
96       requests[index] = Request::irecv_init(static_cast<char *>(recvbuf) + other * recvcount * recvext, recvcount, recvtype,
97                                         other, system_tag, comm);
98       index++;
99     }
100   }
101   Request::startall(2 * (size - 1), requests);
102   (*request)->set_nbc_requests(requests, 2 * (size - 1));
103   return MPI_SUCCESS;
104 }
105
106 int Colls::iscatter(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
107                       void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request* request)
108 {
109   const int system_tag = COLL_TAG_SCATTER;
110   MPI_Aint lb = 0;
111   MPI_Aint sendext = 0;
112
113   int rank = comm->rank();
114   int size = comm->size();
115   (*request) = new Request( nullptr, 0, MPI_BYTE,
116                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
117   if(rank != root) {
118     MPI_Request* requests = new MPI_Request[1];
119     // Recv buffer from root
120     requests[0] = Request::irecv(recvbuf, recvcount, recvtype, root, system_tag, comm);
121     (*request)->set_nbc_requests(requests, 1);
122   } else {
123     sendtype->extent(&lb, &sendext);
124     // Local copy from root
125     if(recvbuf!=MPI_IN_PLACE){
126         Datatype::copy(static_cast<const char *>(sendbuf) + root * sendcount * sendext,
127                            sendcount, sendtype, recvbuf, recvcount, recvtype);
128     }
129     // Send buffers to receivers
130     MPI_Request* requests = new MPI_Request[size - 1];
131     int index = 0;
132     for(int dst = 0; dst < size; dst++) {
133       if(dst != root) {
134         requests[index] = Request::isend_init(static_cast<const char *>(sendbuf) + dst * sendcount * sendext, sendcount, sendtype,
135                                           dst, system_tag, comm);
136         index++;
137       }
138     }
139     // Wait for completion of isend's.
140     Request::startall(size - 1, requests);
141     (*request)->set_nbc_requests(requests, size - 1);
142   }
143   return MPI_SUCCESS;
144 }
145
146 int Colls::iallgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
147                          const int *recvcounts, const int *displs, MPI_Datatype recvtype, MPI_Comm comm, MPI_Request* request)
148 {
149   const int system_tag = COLL_TAG_ALLGATHERV;
150   MPI_Aint lb = 0;
151   MPI_Aint recvext = 0;
152
153   int rank = comm->rank();
154   int size = comm->size();
155   (*request) = new Request( nullptr, 0, MPI_BYTE,
156                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
157   recvtype->extent(&lb, &recvext);
158   // Local copy from self
159   Datatype::copy(sendbuf, sendcount, sendtype,
160                      static_cast<char *>(recvbuf) + displs[rank] * recvext,recvcounts[rank], recvtype);
161   // Send buffers to others;
162   MPI_Request *requests = new MPI_Request[2 * (size - 1)];
163   int index = 0;
164   for (int other = 0; other < size; other++) {
165     if(other != rank) {
166       requests[index] =
167         Request::isend_init(sendbuf, sendcount, sendtype, other, system_tag, comm);
168       index++;
169       requests[index] = Request::irecv_init(static_cast<char *>(recvbuf) + displs[other] * recvext, recvcounts[other],
170                           recvtype, other, system_tag, comm);
171       index++;
172     }
173   }
174   // Wait for completion of all comms.
175   Request::startall(2 * (size - 1), requests);
176   (*request)->set_nbc_requests(requests, 2 * (size - 1));
177   return MPI_SUCCESS;
178 }
179
180 int Colls::ialltoall( const void *sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, MPI_Request* request){
181   int system_tag   = COLL_TAG_ALLTOALL;
182   MPI_Aint lb      = 0;
183   MPI_Aint sendext = 0;
184   MPI_Aint recvext = 0;
185
186   /* Initialize. */
187   int rank = comm->rank();
188   int size = comm->size();
189   (*request) = new Request( nullptr, 0, MPI_BYTE,
190                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
191   sendtype->extent(&lb, &sendext);
192   recvtype->extent(&lb, &recvext);
193   /* simple optimization */
194   int err = Datatype::copy(static_cast<const char *>(sendbuf) + rank * sendcount * sendext, sendcount, sendtype,
195                                static_cast<char *>(recvbuf) + rank * recvcount * recvext, recvcount, recvtype);
196   if (err == MPI_SUCCESS && size > 1) {
197     /* Initiate all send/recv to/from others. */
198     MPI_Request* requests = new MPI_Request[2 * (size - 1)];
199     /* Post all receives first -- a simple optimization */
200     int count = 0;
201     for (int i = (rank + 1) % size; i != rank; i = (i + 1) % size) {
202       requests[count] = Request::irecv_init(static_cast<char *>(recvbuf) + i * recvcount * recvext, recvcount,
203                                         recvtype, i, system_tag, comm);
204       count++;
205     }
206     /* Now post all sends in reverse order
207      *   - We would like to minimize the search time through message queue
208      *     when messages actually arrive in the order in which they were posted.
209      * TODO: check the previous assertion
210      */
211     for (int i = (rank + size - 1) % size; i != rank; i = (i + size - 1) % size) {
212       requests[count] = Request::isend_init(static_cast<const char *>(sendbuf) + i * sendcount * sendext, sendcount,
213                                         sendtype, i, system_tag, comm);
214       count++;
215     }
216     /* Wait for them all. */
217     Request::startall(count, requests);
218     (*request)->set_nbc_requests(requests, count);
219   }
220   return MPI_SUCCESS;
221 }
222
223 int Colls::ialltoallv(const void *sendbuf, const int *sendcounts, const int *senddisps, MPI_Datatype sendtype,
224                               void *recvbuf, const int *recvcounts, const int *recvdisps, MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request){
225   const int system_tag = COLL_TAG_ALLTOALLV;
226   MPI_Aint lb = 0;
227   MPI_Aint sendext = 0;
228   MPI_Aint recvext = 0;
229
230   /* Initialize. */
231   int rank = comm->rank();
232   int size = comm->size();
233   (*request) = new Request( nullptr, 0, MPI_BYTE,
234                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
235   sendtype->extent(&lb, &sendext);
236   recvtype->extent(&lb, &recvext);
237   /* Local copy from self */
238   int err = Datatype::copy(static_cast<const char *>(sendbuf) + senddisps[rank] * sendext, sendcounts[rank], sendtype,
239                                static_cast<char *>(recvbuf) + recvdisps[rank] * recvext, recvcounts[rank], recvtype);
240   if (err == MPI_SUCCESS && size > 1) {
241     /* Initiate all send/recv to/from others. */
242     MPI_Request* requests = new MPI_Request[2 * (size - 1)];
243     int count = 0;
244     /* Create all receives that will be posted first */
245     for (int i = 0; i < size; ++i) {
246       if (i != rank) {
247         requests[count] = Request::irecv_init(static_cast<char *>(recvbuf) + recvdisps[i] * recvext,
248                                           recvcounts[i], recvtype, i, system_tag, comm);
249         count++;
250       }else{
251         XBT_DEBUG("<%d> skip request creation [src = %d, recvcounts[src] = %d]", rank, i, recvcounts[i]);
252       }
253     }
254     /* Now create all sends  */
255     for (int i = 0; i < size; ++i) {
256       if (i != rank) {
257       requests[count] = Request::isend_init(static_cast<const char *>(sendbuf) + senddisps[i] * sendext,
258                                         sendcounts[i], sendtype, i, system_tag, comm);
259       count++;
260       }else{
261         XBT_DEBUG("<%d> skip request creation [dst = %d, sendcounts[dst] = %d]", rank, i, sendcounts[i]);
262       }
263     }
264     /* Wait for them all. */
265     Request::startall(count, requests);
266     (*request)->set_nbc_requests(requests, count);
267   }
268   return err;
269 }
270
271 int Colls::ialltoallw(const void *sendbuf, const int *sendcounts, const int *senddisps, const MPI_Datatype* sendtypes,
272                               void *recvbuf, const int *recvcounts, const int *recvdisps, const MPI_Datatype* recvtypes, MPI_Comm comm, MPI_Request *request){
273   const int system_tag = COLL_TAG_ALLTOALLV;
274
275   /* Initialize. */
276   int rank = comm->rank();
277   int size = comm->size();
278   (*request) = new Request( nullptr, 0, MPI_BYTE,
279                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
280   /* Local copy from self */
281   int err = (sendcounts[rank]>0 && recvcounts[rank]) ? Datatype::copy(static_cast<const char *>(sendbuf) + senddisps[rank], sendcounts[rank], sendtypes[rank],
282                                static_cast<char *>(recvbuf) + recvdisps[rank], recvcounts[rank], recvtypes[rank]): MPI_SUCCESS;
283   if (err == MPI_SUCCESS && size > 1) {
284     /* Initiate all send/recv to/from others. */
285     MPI_Request* requests = new MPI_Request[2 * (size - 1)];
286     int count = 0;
287     /* Create all receives that will be posted first */
288     for (int i = 0; i < size; ++i) {
289       if (i != rank) {
290         requests[count] = Request::irecv_init(static_cast<char *>(recvbuf) + recvdisps[i],
291                                           recvcounts[i], recvtypes[i], i, system_tag, comm);
292         count++;
293       }else{
294         XBT_DEBUG("<%d> skip request creation [src = %d, recvcounts[src] = %d]", rank, i, recvcounts[i]);
295       }
296     }
297     /* Now create all sends  */
298     for (int i = 0; i < size; ++i) {
299       if (i != rank) {
300       requests[count] = Request::isend_init(static_cast<const char *>(sendbuf) + senddisps[i] ,
301                                         sendcounts[i], sendtypes[i], i, system_tag, comm);
302       count++;
303       }else{
304         XBT_DEBUG("<%d> skip request creation [dst = %d, sendcounts[dst] = %d]", rank, i, sendcounts[i]);
305       }
306     }
307     /* Wait for them all. */
308     Request::startall(count, requests);
309     (*request)->set_nbc_requests(requests, count);
310   }
311   return err;
312 }
313
314 int Colls::igather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
315                      void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
316 {
317   const int system_tag = COLL_TAG_GATHER;
318   MPI_Aint lb = 0;
319   MPI_Aint recvext = 0;
320
321   int rank = comm->rank();
322   int size = comm->size();
323   (*request) = new Request( nullptr, 0, MPI_BYTE,
324                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
325   if(rank != root) {
326     // Send buffer to root
327     MPI_Request* requests = new MPI_Request[1];
328     requests[0]=Request::isend(sendbuf, sendcount, sendtype, root, system_tag, comm);
329     (*request)->set_nbc_requests(requests, 1);
330   } else {
331     recvtype->extent(&lb, &recvext);
332     // Local copy from root
333     Datatype::copy(sendbuf, sendcount, sendtype, static_cast<char*>(recvbuf) + root * recvcount * recvext,
334                        recvcount, recvtype);
335     // Receive buffers from senders
336     MPI_Request* requests = new MPI_Request[size - 1];
337     int index = 0;
338     for (int src = 0; src < size; src++) {
339       if(src != root) {
340         requests[index] = Request::irecv_init(static_cast<char*>(recvbuf) + src * recvcount * recvext, recvcount, recvtype,
341                                           src, system_tag, comm);
342         index++;
343       }
344     }
345     // Wait for completion of irecv's.
346     Request::startall(size - 1, requests);
347     (*request)->set_nbc_requests(requests, size - 1);
348   }
349   return MPI_SUCCESS;
350 }
351
352 int Colls::igatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int *recvcounts, const int *displs,
353                       MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
354 {
355   int system_tag = COLL_TAG_GATHERV;
356   MPI_Aint lb = 0;
357   MPI_Aint recvext = 0;
358   
359   int rank = comm->rank();
360   int size = comm->size();
361   (*request) = new Request( nullptr, 0, MPI_BYTE,
362                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
363   if (rank != root) {
364     // Send buffer to root
365     MPI_Request* requests = new MPI_Request[1];
366     requests[0]=Request::isend(sendbuf, sendcount, sendtype, root, system_tag, comm);
367     (*request)->set_nbc_requests(requests, 1);
368   } else {
369     recvtype->extent(&lb, &recvext);
370     // Local copy from root
371     Datatype::copy(sendbuf, sendcount, sendtype, static_cast<char*>(recvbuf) + displs[root] * recvext,
372                        recvcounts[root], recvtype);
373     // Receive buffers from senders
374     MPI_Request* requests = new MPI_Request[size - 1];
375     int index = 0;
376     for (int src = 0; src < size; src++) {
377       if(src != root) {
378         requests[index] = Request::irecv_init(static_cast<char*>(recvbuf) + displs[src] * recvext,
379                           recvcounts[src], recvtype, src, system_tag, comm);
380         index++;
381       }
382     }
383     // Wait for completion of irecv's.
384     Request::startall(size - 1, requests);
385     (*request)->set_nbc_requests(requests, size - 1);
386   }
387   return MPI_SUCCESS;
388 }
389 int Colls::iscatterv(const void *sendbuf, const int *sendcounts, const int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcount,
390                        MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
391 {
392   int system_tag = COLL_TAG_SCATTERV;
393   MPI_Aint lb = 0;
394   MPI_Aint sendext = 0;
395
396   int rank = comm->rank();
397   int size = comm->size();
398   (*request) = new Request( nullptr, 0, MPI_BYTE,
399                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
400   if(rank != root) {
401     // Recv buffer from root
402     MPI_Request* requests = new MPI_Request[1];
403     requests[0]=Request::irecv(recvbuf, recvcount, recvtype, root, system_tag, comm);
404     (*request)->set_nbc_requests(requests, 1);
405   } else {
406     sendtype->extent(&lb, &sendext);
407     // Local copy from root
408     if(recvbuf!=MPI_IN_PLACE){
409       Datatype::copy(static_cast<const char *>(sendbuf) + displs[root] * sendext, sendcounts[root],
410                        sendtype, recvbuf, recvcount, recvtype);
411     }
412     // Send buffers to receivers
413     MPI_Request *requests = new MPI_Request[size - 1];
414     int index = 0;
415     for (int dst = 0; dst < size; dst++) {
416       if (dst != root) {
417         requests[index] = Request::isend_init(static_cast<const char *>(sendbuf) + displs[dst] * sendext, sendcounts[dst],
418                             sendtype, dst, system_tag, comm);
419         index++;
420       }
421     }
422     // Wait for completion of isend's.
423     Request::startall(size - 1, requests);
424     (*request)->set_nbc_requests(requests, size - 1);
425   }
426   return MPI_SUCCESS;
427 }
428
429 int Colls::ireduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root,
430                      MPI_Comm comm, MPI_Request* request)
431 {
432   const int system_tag = COLL_TAG_REDUCE;
433   MPI_Aint lb = 0;
434   MPI_Aint dataext = 0;
435
436   void* sendtmpbuf = const_cast<void *>(sendbuf);
437
438   int rank = comm->rank();
439   int size = comm->size();
440
441   if (size <= 0)
442     return MPI_ERR_COMM;
443
444   if( sendbuf == MPI_IN_PLACE ) {
445     sendtmpbuf = static_cast<void *>(smpi_get_tmp_sendbuffer(count*datatype->get_extent()));
446     Datatype::copy(recvbuf, count, datatype,sendtmpbuf, count, datatype);
447   }
448
449   if(rank == root){
450     (*request) =  new Request( recvbuf, count, datatype,
451                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
452   }
453   else
454     (*request) = new Request( nullptr, count, datatype,
455                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
456
457   if(rank != root) {
458     // Send buffer to root
459     MPI_Request* requests = new MPI_Request[1];
460     requests[0]=Request::isend(sendtmpbuf, count, datatype, root, system_tag, comm);
461     (*request)->set_nbc_requests(requests, 1);
462   } else {
463     datatype->extent(&lb, &dataext);
464     // Local copy from root
465     if (sendtmpbuf != nullptr && recvbuf != nullptr)
466       Datatype::copy(sendtmpbuf, count, datatype, recvbuf, count, datatype);
467     // Receive buffers from senders
468     MPI_Request *requests = new MPI_Request[size - 1];
469     int index = 0;
470     for (int src = 0; src < size; src++) {
471       if (src != root) {
472         requests[index] =
473           Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype, src, system_tag, comm);
474         index++;
475       }
476     }
477     // Wait for completion of irecv's.
478     Request::startall(size - 1, requests);
479     (*request)->set_nbc_requests(requests, size - 1);
480   }     
481   if( sendbuf == MPI_IN_PLACE ) {
482     smpi_free_tmp_buffer(sendtmpbuf);
483   }
484   return MPI_SUCCESS;
485 }
486
487 int Colls::iallreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
488                       MPI_Op op, MPI_Comm comm, MPI_Request* request)
489 {
490
491   const int system_tag = COLL_TAG_ALLREDUCE;
492   MPI_Aint lb = 0;
493   MPI_Aint dataext = 0;
494
495   int rank = comm->rank();
496   int size = comm->size();
497   (*request) = new Request( recvbuf, count, datatype,
498                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
499   // FIXME: check for errors
500   datatype->extent(&lb, &dataext);
501   // Local copy from self
502   Datatype::copy(sendbuf, count, datatype, recvbuf, count, datatype);
503   // Send/Recv buffers to/from others;
504   MPI_Request* requests = new MPI_Request[2 * (size - 1)];
505   int index = 0;
506   for (int other = 0; other < size; other++) {
507     if(other != rank) {
508       requests[index] = Request::isend_init(sendbuf, count, datatype, other, system_tag,comm);
509       index++;
510       requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype,
511                                         other, system_tag, comm);
512       index++;
513     }
514   }
515   Request::startall(2 * (size - 1), requests);
516   (*request)->set_nbc_requests(requests, 2 * (size - 1));
517   return MPI_SUCCESS;
518 }
519
520 int Colls::iscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request* request)
521 {
522   int system_tag = -888;
523   MPI_Aint lb      = 0;
524   MPI_Aint dataext = 0;
525
526   int rank = comm->rank();
527   int size = comm->size();
528   (*request) = new Request( recvbuf, count, datatype,
529                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
530   datatype->extent(&lb, &dataext);
531
532   // Local copy from self
533   Datatype::copy(sendbuf, count, datatype, recvbuf, count, datatype);
534
535   // Send/Recv buffers to/from others
536   MPI_Request *requests = new MPI_Request[size - 1];
537   int index = 0;
538   for (int other = 0; other < rank; other++) {
539     requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype, other, system_tag, comm);
540     index++;
541   }
542   for (int other = rank + 1; other < size; other++) {
543     requests[index] = Request::isend_init(sendbuf, count, datatype, other, system_tag, comm);
544     index++;
545   }
546   // Wait for completion of all comms.
547   Request::startall(size - 1, requests);
548   (*request)->set_nbc_requests(requests, size - 1);
549   return MPI_SUCCESS;
550 }
551
552 int Colls::iexscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request* request)
553 {
554   int system_tag = -888;
555   MPI_Aint lb         = 0;
556   MPI_Aint dataext    = 0;
557   int rank = comm->rank();
558   int size = comm->size();
559   (*request) = new Request( recvbuf, count, datatype,
560                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
561   datatype->extent(&lb, &dataext);
562   if(rank != 0)
563     memset(recvbuf, 0, count*dataext);
564
565   // Send/Recv buffers to/from others
566   MPI_Request *requests = new MPI_Request[size - 1];
567   int index = 0;
568   for (int other = 0; other < rank; other++) {
569     requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype, other, system_tag, comm);
570     index++;
571   }
572   for (int other = rank + 1; other < size; other++) {
573     requests[index] = Request::isend_init(sendbuf, count, datatype, other, system_tag, comm);
574     index++;
575   }
576   // Wait for completion of all comms.
577   Request::startall(size - 1, requests);
578   (*request)->set_nbc_requests(requests, size - 1);
579   return MPI_SUCCESS;
580 }
581
582 int Colls::ireduce_scatter(const void *sendbuf, void *recvbuf, const int *recvcounts, MPI_Datatype datatype, MPI_Op op,
583                              MPI_Comm comm, MPI_Request* request){
584 //Version where each process performs the reduce for its own part. Alltoall pattern for comms.
585   const int system_tag = COLL_TAG_REDUCE_SCATTER;
586   MPI_Aint lb = 0;
587   MPI_Aint dataext = 0;
588
589   int rank = comm->rank();
590   int size = comm->size();
591   int count=recvcounts[rank];
592   (*request) = new Request( recvbuf, count, datatype,
593                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
594   datatype->extent(&lb, &dataext);
595
596   // Send/Recv buffers to/from others;
597   MPI_Request* requests = new MPI_Request[2 * (size - 1)];
598   int index = 0;
599   int recvdisp=0;
600   for (int other = 0; other < size; other++) {
601     if(other != rank) {
602       requests[index] = Request::isend_init(static_cast<const char *>(sendbuf) + recvdisp * dataext, recvcounts[other], datatype, other, system_tag,comm);
603       XBT_VERB("sending with recvdisp %d", recvdisp);
604       index++;
605       requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype,
606                                         other, system_tag, comm);
607       index++;
608     }else{
609       Datatype::copy(static_cast<const char *>(sendbuf) + recvdisp * dataext, count, datatype, recvbuf, count, datatype);
610     }
611     recvdisp+=recvcounts[other];
612   }
613   Request::startall(2 * (size - 1), requests);
614   (*request)->set_nbc_requests(requests, 2 * (size - 1));
615   return MPI_SUCCESS;
616 }
617
618 }
619 }