Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[cppcheck] Reduce scope for variables.
[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(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(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<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<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(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
147                          int *recvcounts, 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( 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, sendext = 0, recvext = 0;
183
184   /* Initialize. */
185   int rank = comm->rank();
186   int size = comm->size();
187   (*request) = new Request( nullptr, 0, MPI_BYTE,
188                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
189   sendtype->extent(&lb, &sendext);
190   recvtype->extent(&lb, &recvext);
191   /* simple optimization */
192   int err = Datatype::copy(static_cast<char *>(sendbuf) + rank * sendcount * sendext, sendcount, sendtype,
193                                static_cast<char *>(recvbuf) + rank * recvcount * recvext, recvcount, recvtype);
194   if (err == MPI_SUCCESS && size > 1) {
195     /* Initiate all send/recv to/from others. */
196     MPI_Request* requests = new MPI_Request[2 * (size - 1)];
197     /* Post all receives first -- a simple optimization */
198     int count = 0;
199     for (int i = (rank + 1) % size; i != rank; i = (i + 1) % size) {
200       requests[count] = Request::irecv_init(static_cast<char *>(recvbuf) + i * recvcount * recvext, recvcount,
201                                         recvtype, i, system_tag, comm);
202       count++;
203     }
204     /* Now post all sends in reverse order
205      *   - We would like to minimize the search time through message queue
206      *     when messages actually arrive in the order in which they were posted.
207      * TODO: check the previous assertion
208      */
209     for (int i = (rank + size - 1) % size; i != rank; i = (i + size - 1) % size) {
210       requests[count] = Request::isend_init(static_cast<char *>(sendbuf) + i * sendcount * sendext, sendcount,
211                                         sendtype, i, system_tag, comm);
212       count++;
213     }
214     /* Wait for them all. */
215     Request::startall(count, requests);
216     (*request)->set_nbc_requests(requests, count);
217   }
218   return MPI_SUCCESS;
219 }
220
221 int Colls::ialltoallv(void *sendbuf, int *sendcounts, int *senddisps, MPI_Datatype sendtype,
222                               void *recvbuf, int *recvcounts, int *recvdisps, MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request){
223   const int system_tag = COLL_TAG_ALLTOALLV;
224   MPI_Aint lb = 0;
225   MPI_Aint sendext = 0;
226   MPI_Aint recvext = 0;
227
228   /* Initialize. */
229   int rank = comm->rank();
230   int size = comm->size();
231   (*request) = new Request( nullptr, 0, MPI_BYTE,
232                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
233   sendtype->extent(&lb, &sendext);
234   recvtype->extent(&lb, &recvext);
235   /* Local copy from self */
236   int err = Datatype::copy(static_cast<char *>(sendbuf) + senddisps[rank] * sendext, sendcounts[rank], sendtype,
237                                static_cast<char *>(recvbuf) + recvdisps[rank] * recvext, recvcounts[rank], recvtype);
238   if (err == MPI_SUCCESS && size > 1) {
239     /* Initiate all send/recv to/from others. */
240     MPI_Request* requests = new MPI_Request[2 * (size - 1)];
241     int count = 0;
242     /* Create all receives that will be posted first */
243     for (int i = 0; i < size; ++i) {
244       if (i != rank) {
245         requests[count] = Request::irecv_init(static_cast<char *>(recvbuf) + recvdisps[i] * recvext,
246                                           recvcounts[i], recvtype, i, system_tag, comm);
247         count++;
248       }else{
249         XBT_DEBUG("<%d> skip request creation [src = %d, recvcounts[src] = %d]", rank, i, recvcounts[i]);
250       }
251     }
252     /* Now create all sends  */
253     for (int i = 0; i < size; ++i) {
254       if (i != rank) {
255       requests[count] = Request::isend_init(static_cast<char *>(sendbuf) + senddisps[i] * sendext,
256                                         sendcounts[i], sendtype, i, system_tag, comm);
257       count++;
258       }else{
259         XBT_DEBUG("<%d> skip request creation [dst = %d, sendcounts[dst] = %d]", rank, i, sendcounts[i]);
260       }
261     }
262     /* Wait for them all. */
263     Request::startall(count, requests);
264     (*request)->set_nbc_requests(requests, count);
265   }
266   return err;
267 }
268
269 int Colls::ialltoallw(void *sendbuf, int *sendcounts, int *senddisps, MPI_Datatype* sendtypes,
270                               void *recvbuf, int *recvcounts, int *recvdisps, MPI_Datatype* recvtypes, MPI_Comm comm, MPI_Request *request){
271   const int system_tag = COLL_TAG_ALLTOALLV;
272
273   /* Initialize. */
274   int rank = comm->rank();
275   int size = comm->size();
276   (*request) = new Request( nullptr, 0, MPI_BYTE,
277                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
278   /* Local copy from self */
279   int err = (sendcounts[rank]>0 && recvcounts[rank]) ? Datatype::copy(static_cast<char *>(sendbuf) + senddisps[rank], sendcounts[rank], sendtypes[rank],
280                                static_cast<char *>(recvbuf) + recvdisps[rank], recvcounts[rank], recvtypes[rank]): MPI_SUCCESS;
281   if (err == MPI_SUCCESS && size > 1) {
282     /* Initiate all send/recv to/from others. */
283     MPI_Request* requests = new MPI_Request[2 * (size - 1)];
284     int count = 0;
285     /* Create all receives that will be posted first */
286     for (int i = 0; i < size; ++i) {
287       if (i != rank) {
288         requests[count] = Request::irecv_init(static_cast<char *>(recvbuf) + recvdisps[i],
289                                           recvcounts[i], recvtypes[i], i, system_tag, comm);
290         count++;
291       }else{
292         XBT_DEBUG("<%d> skip request creation [src = %d, recvcounts[src] = %d]", rank, i, recvcounts[i]);
293       }
294     }
295     /* Now create all sends  */
296     for (int i = 0; i < size; ++i) {
297       if (i != rank) {
298       requests[count] = Request::isend_init(static_cast<char *>(sendbuf) + senddisps[i] ,
299                                         sendcounts[i], sendtypes[i], i, system_tag, comm);
300       count++;
301       }else{
302         XBT_DEBUG("<%d> skip request creation [dst = %d, sendcounts[dst] = %d]", rank, i, sendcounts[i]);
303       }
304     }
305     /* Wait for them all. */
306     Request::startall(count, requests);
307     (*request)->set_nbc_requests(requests, count);
308   }
309   return err;
310 }
311
312 int Colls::igather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
313                      void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
314 {
315   const int system_tag = COLL_TAG_GATHER;
316   MPI_Aint lb = 0;
317   MPI_Aint recvext = 0;
318
319   int rank = comm->rank();
320   int size = comm->size();
321   (*request) = new Request( nullptr, 0, MPI_BYTE,
322                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
323   if(rank != root) {
324     // Send buffer to root
325     MPI_Request* requests = new MPI_Request[1];
326     requests[0]=Request::isend(sendbuf, sendcount, sendtype, root, system_tag, comm);
327     (*request)->set_nbc_requests(requests, 1);
328   } else {
329     recvtype->extent(&lb, &recvext);
330     // Local copy from root
331     Datatype::copy(sendbuf, sendcount, sendtype, static_cast<char*>(recvbuf) + root * recvcount * recvext,
332                        recvcount, recvtype);
333     // Receive buffers from senders
334     MPI_Request* requests = new MPI_Request[size - 1];
335     int index = 0;
336     for (int src = 0; src < size; src++) {
337       if(src != root) {
338         requests[index] = Request::irecv_init(static_cast<char*>(recvbuf) + src * recvcount * recvext, recvcount, recvtype,
339                                           src, system_tag, comm);
340         index++;
341       }
342     }
343     // Wait for completion of irecv's.
344     Request::startall(size - 1, requests);
345     (*request)->set_nbc_requests(requests, size - 1);
346   }
347   return MPI_SUCCESS;
348 }
349
350 int Colls::igatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcounts, int *displs,
351                       MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
352 {
353   int system_tag = COLL_TAG_GATHERV;
354   MPI_Aint lb = 0;
355   MPI_Aint recvext = 0;
356   
357   int rank = comm->rank();
358   int size = comm->size();
359   (*request) = new Request( nullptr, 0, MPI_BYTE,
360                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
361   if (rank != root) {
362     // Send buffer to root
363     MPI_Request* requests = new MPI_Request[1];
364     requests[0]=Request::isend(sendbuf, sendcount, sendtype, root, system_tag, comm);
365     (*request)->set_nbc_requests(requests, 1);
366   } else {
367     recvtype->extent(&lb, &recvext);
368     // Local copy from root
369     Datatype::copy(sendbuf, sendcount, sendtype, static_cast<char*>(recvbuf) + displs[root] * recvext,
370                        recvcounts[root], recvtype);
371     // Receive buffers from senders
372     MPI_Request* requests = new MPI_Request[size - 1];
373     int index = 0;
374     for (int src = 0; src < size; src++) {
375       if(src != root) {
376         requests[index] = Request::irecv_init(static_cast<char*>(recvbuf) + displs[src] * recvext,
377                           recvcounts[src], recvtype, src, system_tag, comm);
378         index++;
379       }
380     }
381     // Wait for completion of irecv's.
382     Request::startall(size - 1, requests);
383     (*request)->set_nbc_requests(requests, size - 1);
384   }
385   return MPI_SUCCESS;
386 }
387 int Colls::iscatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcount,
388                        MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
389 {
390   int system_tag = COLL_TAG_SCATTERV;
391   MPI_Aint lb = 0;
392   MPI_Aint sendext = 0;
393
394   int rank = comm->rank();
395   int size = comm->size();
396   (*request) = new Request( nullptr, 0, MPI_BYTE,
397                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
398   if(rank != root) {
399     // Recv buffer from root
400     MPI_Request* requests = new MPI_Request[1];
401     requests[0]=Request::irecv(recvbuf, recvcount, recvtype, root, system_tag, comm);
402     (*request)->set_nbc_requests(requests, 1);
403   } else {
404     sendtype->extent(&lb, &sendext);
405     // Local copy from root
406     if(recvbuf!=MPI_IN_PLACE){
407       Datatype::copy(static_cast<char *>(sendbuf) + displs[root] * sendext, sendcounts[root],
408                        sendtype, recvbuf, recvcount, recvtype);
409     }
410     // Send buffers to receivers
411     MPI_Request *requests = new MPI_Request[size - 1];
412     int index = 0;
413     for (int dst = 0; dst < size; dst++) {
414       if (dst != root) {
415         requests[index] = Request::isend_init(static_cast<char *>(sendbuf) + displs[dst] * sendext, sendcounts[dst],
416                             sendtype, dst, system_tag, comm);
417         index++;
418       }
419     }
420     // Wait for completion of isend's.
421     Request::startall(size - 1, requests);
422     (*request)->set_nbc_requests(requests, size - 1);
423   }
424   return MPI_SUCCESS;
425 }
426
427 int Colls::ireduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root,
428                      MPI_Comm comm, MPI_Request* request)
429 {
430   const int system_tag = COLL_TAG_REDUCE;
431   MPI_Aint lb = 0;
432   MPI_Aint dataext = 0;
433
434   char* sendtmpbuf = static_cast<char *>(sendbuf);
435
436   int rank = comm->rank();
437   int size = comm->size();
438
439   if (size <= 0)
440     return MPI_ERR_COMM;
441
442   if( sendbuf == MPI_IN_PLACE ) {
443     sendtmpbuf = static_cast<char *>(smpi_get_tmp_sendbuffer(count*datatype->get_extent()));
444     Datatype::copy(recvbuf, count, datatype,sendtmpbuf, count, datatype);
445   }
446
447   if(rank == root){
448     (*request) =  new Request( recvbuf, count, datatype,
449                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
450   }
451   else
452     (*request) = new Request( nullptr, count, datatype,
453                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT);
454
455   if(rank != root) {
456     // Send buffer to root
457     MPI_Request* requests = new MPI_Request[1];
458     requests[0]=Request::isend(sendtmpbuf, count, datatype, root, system_tag, comm);
459     (*request)->set_nbc_requests(requests, 1);
460   } else {
461     datatype->extent(&lb, &dataext);
462     // Local copy from root
463     if (sendtmpbuf != nullptr && recvbuf != nullptr)
464       Datatype::copy(sendtmpbuf, count, datatype, recvbuf, count, datatype);
465     // Receive buffers from senders
466     MPI_Request *requests = new MPI_Request[size - 1];
467     int index = 0;
468     for (int src = 0; src < size; src++) {
469       if (src != root) {
470         requests[index] =
471           Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype, src, system_tag, comm);
472         index++;
473       }
474     }
475     // Wait for completion of irecv's.
476     Request::startall(size - 1, requests);
477     (*request)->set_nbc_requests(requests, size - 1);
478   }     
479   if( sendbuf == MPI_IN_PLACE ) {
480     smpi_free_tmp_buffer(sendtmpbuf);
481   }
482   return MPI_SUCCESS;
483 }
484
485 int Colls::iallreduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
486                       MPI_Op op, MPI_Comm comm, MPI_Request* request)
487 {
488
489   const int system_tag = COLL_TAG_ALLREDUCE;
490   MPI_Aint lb = 0;
491   MPI_Aint dataext = 0;
492
493   int rank = comm->rank();
494   int size = comm->size();
495   (*request) = new Request( recvbuf, count, datatype,
496                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
497   // FIXME: check for errors
498   datatype->extent(&lb, &dataext);
499   // Local copy from self
500   Datatype::copy(sendbuf, count, datatype, recvbuf, count, datatype);
501   // Send/Recv buffers to/from others;
502   MPI_Request* requests = new MPI_Request[2 * (size - 1)];
503   int index = 0;
504   for (int other = 0; other < size; other++) {
505     if(other != rank) {
506       requests[index] = Request::isend_init(sendbuf, count, datatype, other, system_tag,comm);
507       index++;
508       requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype,
509                                         other, system_tag, comm);
510       index++;
511     }
512   }
513   Request::startall(2 * (size - 1), requests);
514   (*request)->set_nbc_requests(requests, 2 * (size - 1));
515   return MPI_SUCCESS;
516 }
517
518 int Colls::iscan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request* request)
519 {
520   int system_tag = -888;
521   MPI_Aint lb      = 0;
522   MPI_Aint dataext = 0;
523
524   int rank = comm->rank();
525   int size = comm->size();
526   (*request) = new Request( recvbuf, count, datatype,
527                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
528   datatype->extent(&lb, &dataext);
529
530   // Local copy from self
531   Datatype::copy(sendbuf, count, datatype, recvbuf, count, datatype);
532
533   // Send/Recv buffers to/from others
534   MPI_Request *requests = new MPI_Request[size - 1];
535   int index = 0;
536   for (int other = 0; other < rank; other++) {
537     requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype, other, system_tag, comm);
538     index++;
539   }
540   for (int other = rank + 1; other < size; other++) {
541     requests[index] = Request::isend_init(sendbuf, count, datatype, other, system_tag, comm);
542     index++;
543   }
544   // Wait for completion of all comms.
545   Request::startall(size - 1, requests);
546   (*request)->set_nbc_requests(requests, size - 1);
547   return MPI_SUCCESS;
548 }
549
550 int Colls::iexscan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, MPI_Request* request)
551 {
552   int system_tag = -888;
553   MPI_Aint lb         = 0;
554   MPI_Aint dataext    = 0;
555   int rank = comm->rank();
556   int size = comm->size();
557   (*request) = new Request( recvbuf, count, datatype,
558                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
559   datatype->extent(&lb, &dataext);
560   if(rank != 0)
561     memset(recvbuf, 0, count*dataext);
562
563   // Send/Recv buffers to/from others
564   MPI_Request *requests = new MPI_Request[size - 1];
565   int index = 0;
566   for (int other = 0; other < rank; other++) {
567     requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype, other, system_tag, comm);
568     index++;
569   }
570   for (int other = rank + 1; other < size; other++) {
571     requests[index] = Request::isend_init(sendbuf, count, datatype, other, system_tag, comm);
572     index++;
573   }
574   // Wait for completion of all comms.
575   Request::startall(size - 1, requests);
576   (*request)->set_nbc_requests(requests, size - 1);
577   return MPI_SUCCESS;
578 }
579
580 int Colls::ireduce_scatter(void *sendbuf, void *recvbuf, int *recvcounts, MPI_Datatype datatype, MPI_Op op,
581                              MPI_Comm comm, MPI_Request* request){
582 //Version where each process performs the reduce for its own part. Alltoall pattern for comms.
583   const int system_tag = COLL_TAG_REDUCE_SCATTER;
584   MPI_Aint lb = 0;
585   MPI_Aint dataext = 0;
586
587   int rank = comm->rank();
588   int size = comm->size();
589   int count=recvcounts[rank];
590   (*request) = new Request( recvbuf, count, datatype,
591                          rank,rank, system_tag, comm, MPI_REQ_PERSISTENT, op);
592   datatype->extent(&lb, &dataext);
593
594   // Send/Recv buffers to/from others;
595   MPI_Request* requests = new MPI_Request[2 * (size - 1)];
596   int index = 0;
597   int recvdisp=0;
598   for (int other = 0; other < size; other++) {
599     if(other != rank) {
600       requests[index] = Request::isend_init(static_cast<char *>(sendbuf) + recvdisp * dataext, recvcounts[other], datatype, other, system_tag,comm);
601       XBT_VERB("sending with recvdisp %d", recvdisp);
602       index++;
603       requests[index] = Request::irecv_init(smpi_get_tmp_sendbuffer(count * dataext), count, datatype,
604                                         other, system_tag, comm);
605       index++;
606     }else{
607       Datatype::copy(static_cast<char *>(sendbuf) + recvdisp * dataext, count, datatype, recvbuf, count, datatype);
608     }
609     recvdisp+=recvcounts[other];
610   }
611   Request::startall(2 * (size - 1), requests);
612   (*request)->set_nbc_requests(requests, 2 * (size - 1));
613   return MPI_SUCCESS;
614 }
615
616 }
617 }