Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
8c246d8d09d30b9294501f598b8452af267f8739
[simgrid.git] / src / smpi / bindings / smpi_pmpi_coll.cpp
1 /* Copyright (c) 2007-2018. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "private.hpp"
7 #include "smpi_coll.hpp"
8 #include "smpi_comm.hpp"
9 #include "smpi_datatype_derived.hpp"
10 #include "smpi_op.hpp"
11 #include "smpi_process.hpp"
12
13 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smpi_pmpi);
14
15 /* PMPI User level calls */
16
17 int PMPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm)
18 {
19   int retval = 0;
20
21   smpi_bench_end();
22
23   if (comm == MPI_COMM_NULL) {
24     retval = MPI_ERR_COMM;
25   } else if (not datatype->is_valid()) {
26     retval = MPI_ERR_ARG;
27   } else {
28     int rank = simgrid::s4u::this_actor::get_pid();
29     TRACE_smpi_comm_in(rank, __func__,
30                        new simgrid::instr::CollTIData("bcast", root, -1.0,
31                                                       datatype->is_replayable() ? count : count * datatype->size(), -1,
32                                                       simgrid::smpi::Datatype::encode(datatype), ""));
33     if (comm->size() > 1)
34       simgrid::smpi::Colls::bcast(buf, count, datatype, root, comm);
35     retval = MPI_SUCCESS;
36
37     TRACE_smpi_comm_out(rank);
38   }
39   smpi_bench_begin();
40   return retval;
41 }
42
43 int PMPI_Barrier(MPI_Comm comm)
44 {
45   int retval = 0;
46
47   smpi_bench_end();
48
49   if (comm == MPI_COMM_NULL) {
50     retval = MPI_ERR_COMM;
51   } else {
52     int rank = simgrid::s4u::this_actor::get_pid();
53     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::NoOpTIData("barrier"));
54
55     simgrid::smpi::Colls::barrier(comm);
56
57     //Barrier can be used to synchronize RMA calls. Finish all requests from comm before.
58     comm->finish_rma_calls();
59
60     retval = MPI_SUCCESS;
61
62     TRACE_smpi_comm_out(rank);
63   }
64
65   smpi_bench_begin();
66   return retval;
67 }
68
69 int PMPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,void *recvbuf, int recvcount, MPI_Datatype recvtype,
70                 int root, MPI_Comm comm)
71 {
72   int retval = 0;
73
74   smpi_bench_end();
75
76   if (comm == MPI_COMM_NULL) {
77     retval = MPI_ERR_COMM;
78   } else if ((( sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) ||
79             ((comm->rank() == root) && (recvtype == MPI_DATATYPE_NULL))){
80     retval = MPI_ERR_TYPE;
81   } else if ((( sendbuf != MPI_IN_PLACE) && (sendcount <0)) || ((comm->rank() == root) && (recvcount <0))){
82     retval = MPI_ERR_COUNT;
83   } else {
84
85     char* sendtmpbuf = static_cast<char*>(sendbuf);
86     int sendtmpcount = sendcount;
87     MPI_Datatype sendtmptype = sendtype;
88     if( (comm->rank() == root) && (sendbuf == MPI_IN_PLACE )) {
89       sendtmpcount=0;
90       sendtmptype=recvtype;
91     }
92     int rank = simgrid::s4u::this_actor::get_pid();
93
94     TRACE_smpi_comm_in(
95         rank, __func__,
96         new simgrid::instr::CollTIData(
97             "gather", root, -1.0, sendtmptype->is_replayable() ? sendtmpcount : sendtmpcount * sendtmptype->size(),
98             (comm->rank() != root || recvtype->is_replayable()) ? recvcount : recvcount * recvtype->size(),
99             simgrid::smpi::Datatype::encode(sendtmptype), simgrid::smpi::Datatype::encode(recvtype)));
100
101     simgrid::smpi::Colls::gather(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcount, recvtype, root, comm);
102
103     retval = MPI_SUCCESS;
104     TRACE_smpi_comm_out(rank);
105   }
106
107   smpi_bench_begin();
108   return retval;
109 }
110
111 int PMPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcounts, int *displs,
112                 MPI_Datatype recvtype, int root, MPI_Comm comm)
113 {
114   int retval = 0;
115
116   smpi_bench_end();
117
118   if (comm == MPI_COMM_NULL) {
119     retval = MPI_ERR_COMM;
120   } else if ((( sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) ||
121             ((comm->rank() == root) && (recvtype == MPI_DATATYPE_NULL))){
122     retval = MPI_ERR_TYPE;
123   } else if (( sendbuf != MPI_IN_PLACE) && (sendcount <0)){
124     retval = MPI_ERR_COUNT;
125   } else if ((comm->rank() == root) && (recvcounts == nullptr || displs == nullptr)) {
126     retval = MPI_ERR_ARG;
127   } else {
128     char* sendtmpbuf = static_cast<char*>(sendbuf);
129     int sendtmpcount = sendcount;
130     MPI_Datatype sendtmptype = sendtype;
131     if( (comm->rank() == root) && (sendbuf == MPI_IN_PLACE )) {
132       sendtmpcount=0;
133       sendtmptype=recvtype;
134     }
135
136     int rank         = simgrid::s4u::this_actor::get_pid();
137     int dt_size_recv = recvtype->is_replayable() ? 1 : recvtype->size();
138
139     std::vector<int>* trace_recvcounts = new std::vector<int>;
140     if (comm->rank() == root) {
141       for (int i = 0; i < comm->size(); i++) // copy data to avoid bad free
142         trace_recvcounts->push_back(recvcounts[i] * dt_size_recv);
143     }
144
145     TRACE_smpi_comm_in(rank, __func__,
146                        new simgrid::instr::VarCollTIData(
147                            "gatherV", root,
148                            sendtmptype->is_replayable() ? sendtmpcount : sendtmpcount * sendtmptype->size(), nullptr,
149                            dt_size_recv, trace_recvcounts, simgrid::smpi::Datatype::encode(sendtmptype),
150                            simgrid::smpi::Datatype::encode(recvtype)));
151
152     retval = simgrid::smpi::Colls::gatherv(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcounts, displs, recvtype, root, comm);
153     TRACE_smpi_comm_out(rank);
154   }
155
156   smpi_bench_begin();
157   return retval;
158 }
159
160 int PMPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
161                    void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
162 {
163   int retval = MPI_SUCCESS;
164
165   smpi_bench_end();
166
167   if (comm == MPI_COMM_NULL) {
168     retval = MPI_ERR_COMM;
169   } else if ((( sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) ||
170             (recvtype == MPI_DATATYPE_NULL)){
171     retval = MPI_ERR_TYPE;
172   } else if ((( sendbuf != MPI_IN_PLACE) && (sendcount <0)) ||
173             (recvcount <0)){
174     retval = MPI_ERR_COUNT;
175   } else {
176     if(sendbuf == MPI_IN_PLACE) {
177       sendbuf=static_cast<char*>(recvbuf)+recvtype->get_extent()*recvcount*comm->rank();
178       sendcount=recvcount;
179       sendtype=recvtype;
180     }
181     int rank = simgrid::s4u::this_actor::get_pid();
182
183     TRACE_smpi_comm_in(rank, __func__,
184                        new simgrid::instr::CollTIData(
185                            "allGather", -1, -1.0, sendtype->is_replayable() ? sendcount : sendcount * sendtype->size(),
186                            recvtype->is_replayable() ? recvcount : recvcount * recvtype->size(),
187                            simgrid::smpi::Datatype::encode(sendtype), simgrid::smpi::Datatype::encode(recvtype)));
188
189     simgrid::smpi::Colls::allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
190     TRACE_smpi_comm_out(rank);
191   }
192   smpi_bench_begin();
193   return retval;
194 }
195
196 int PMPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
197                    void *recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype, MPI_Comm comm)
198 {
199   int retval = 0;
200
201   smpi_bench_end();
202
203   if (comm == MPI_COMM_NULL) {
204     retval = MPI_ERR_COMM;
205   } else if (((sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) || (recvtype == MPI_DATATYPE_NULL)) {
206     retval = MPI_ERR_TYPE;
207   } else if (( sendbuf != MPI_IN_PLACE) && (sendcount <0)){
208     retval = MPI_ERR_COUNT;
209   } else if (recvcounts == nullptr || displs == nullptr) {
210     retval = MPI_ERR_ARG;
211   } else {
212
213     if(sendbuf == MPI_IN_PLACE) {
214       sendbuf=static_cast<char*>(recvbuf)+recvtype->get_extent()*displs[comm->rank()];
215       sendcount=recvcounts[comm->rank()];
216       sendtype=recvtype;
217     }
218     int rank               = simgrid::s4u::this_actor::get_pid();
219     int dt_size_recv       = recvtype->is_replayable() ? 1 : recvtype->size();
220
221     std::vector<int>* trace_recvcounts = new std::vector<int>;
222     for (int i = 0; i < comm->size(); i++) // copy data to avoid bad free
223       trace_recvcounts->push_back(recvcounts[i] * dt_size_recv);
224
225     TRACE_smpi_comm_in(rank, __func__,
226                        new simgrid::instr::VarCollTIData(
227                            "allGatherV", -1, sendtype->is_replayable() ? sendcount : sendcount * sendtype->size(),
228                            nullptr, dt_size_recv, trace_recvcounts, simgrid::smpi::Datatype::encode(sendtype),
229                            simgrid::smpi::Datatype::encode(recvtype)));
230
231     simgrid::smpi::Colls::allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm);
232     retval = MPI_SUCCESS;
233     TRACE_smpi_comm_out(rank);
234   }
235
236   smpi_bench_begin();
237   return retval;
238 }
239
240 int PMPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
241                 void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
242 {
243   int retval = 0;
244
245   smpi_bench_end();
246
247   if (comm == MPI_COMM_NULL) {
248     retval = MPI_ERR_COMM;
249   } else if (((comm->rank() == root) && (not sendtype->is_valid())) ||
250              ((recvbuf != MPI_IN_PLACE) && (not recvtype->is_valid()))) {
251     retval = MPI_ERR_TYPE;
252   } else if ((sendbuf == recvbuf) ||
253       ((comm->rank()==root) && sendcount>0 && (sendbuf == nullptr))){
254     retval = MPI_ERR_BUFFER;
255   }else {
256
257     if (recvbuf == MPI_IN_PLACE) {
258       recvtype  = sendtype;
259       recvcount = sendcount;
260     }
261     int rank = simgrid::s4u::this_actor::get_pid();
262
263     TRACE_smpi_comm_in(
264         rank, __func__,
265         new simgrid::instr::CollTIData(
266             "scatter", root, -1.0,
267             (comm->rank() != root || sendtype->is_replayable()) ? sendcount : sendcount * sendtype->size(),
268             recvtype->is_replayable() ? recvcount : recvcount * recvtype->size(),
269             simgrid::smpi::Datatype::encode(sendtype), simgrid::smpi::Datatype::encode(recvtype)));
270
271     simgrid::smpi::Colls::scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm);
272     retval = MPI_SUCCESS;
273     TRACE_smpi_comm_out(rank);
274   }
275
276   smpi_bench_begin();
277   return retval;
278 }
279
280 int PMPI_Scatterv(void *sendbuf, int *sendcounts, int *displs,
281                  MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
282 {
283   int retval = 0;
284
285   smpi_bench_end();
286
287   if (comm == MPI_COMM_NULL) {
288     retval = MPI_ERR_COMM;
289   } else if (sendcounts == nullptr || displs == nullptr) {
290     retval = MPI_ERR_ARG;
291   } else if (((comm->rank() == root) && (sendtype == MPI_DATATYPE_NULL)) ||
292              ((recvbuf != MPI_IN_PLACE) && (recvtype == MPI_DATATYPE_NULL))) {
293     retval = MPI_ERR_TYPE;
294   } else {
295     if (recvbuf == MPI_IN_PLACE) {
296       recvtype  = sendtype;
297       recvcount = sendcounts[comm->rank()];
298     }
299     int rank               = simgrid::s4u::this_actor::get_pid();
300     int dt_size_send       = sendtype->is_replayable() ? 1 : sendtype->size();
301
302     std::vector<int>* trace_sendcounts = new std::vector<int>;
303     if (comm->rank() == root) {
304       for (int i = 0; i < comm->size(); i++) // copy data to avoid bad free
305         trace_sendcounts->push_back(sendcounts[i] * dt_size_send);
306     }
307
308     TRACE_smpi_comm_in(rank, __func__,
309                        new simgrid::instr::VarCollTIData(
310                            "scatterV", root, dt_size_send, trace_sendcounts,
311                            recvtype->is_replayable() ? recvcount : recvcount * recvtype->size(), nullptr,
312                            simgrid::smpi::Datatype::encode(sendtype), simgrid::smpi::Datatype::encode(recvtype)));
313
314     retval = simgrid::smpi::Colls::scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm);
315
316     TRACE_smpi_comm_out(rank);
317   }
318
319   smpi_bench_begin();
320   return retval;
321 }
322
323 int PMPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
324 {
325   int retval = 0;
326
327   smpi_bench_end();
328
329   if (comm == MPI_COMM_NULL) {
330     retval = MPI_ERR_COMM;
331   } else if (not datatype->is_valid() || op == MPI_OP_NULL) {
332     retval = MPI_ERR_ARG;
333   } else {
334     int rank = simgrid::s4u::this_actor::get_pid();
335
336     TRACE_smpi_comm_in(rank, __func__,
337                        new simgrid::instr::CollTIData("reduce", root, 0,
338                                                       datatype->is_replayable() ? count : count * datatype->size(), -1,
339                                                       simgrid::smpi::Datatype::encode(datatype), ""));
340
341     simgrid::smpi::Colls::reduce(sendbuf, recvbuf, count, datatype, op, root, comm);
342
343     retval = MPI_SUCCESS;
344     TRACE_smpi_comm_out(rank);
345   }
346
347   smpi_bench_begin();
348   return retval;
349 }
350
351 int PMPI_Reduce_local(void *inbuf, void *inoutbuf, int count, MPI_Datatype datatype, MPI_Op op){
352   int retval = 0;
353
354   smpi_bench_end();
355   if (not datatype->is_valid() || op == MPI_OP_NULL) {
356     retval = MPI_ERR_ARG;
357   } else {
358     op->apply(inbuf, inoutbuf, &count, datatype);
359     retval = MPI_SUCCESS;
360   }
361   smpi_bench_begin();
362   return retval;
363 }
364
365 int PMPI_Allreduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
366 {
367   int retval = 0;
368
369   smpi_bench_end();
370
371   if (comm == MPI_COMM_NULL) {
372     retval = MPI_ERR_COMM;
373   } else if (not datatype->is_valid()) {
374     retval = MPI_ERR_TYPE;
375   } else if (op == MPI_OP_NULL) {
376     retval = MPI_ERR_OP;
377   } else {
378
379     char* sendtmpbuf = static_cast<char*>(sendbuf);
380     if( sendbuf == MPI_IN_PLACE ) {
381       sendtmpbuf = static_cast<char*>(xbt_malloc(count*datatype->get_extent()));
382       simgrid::smpi::Datatype::copy(recvbuf, count, datatype,sendtmpbuf, count, datatype);
383     }
384     int rank = simgrid::s4u::this_actor::get_pid();
385
386     TRACE_smpi_comm_in(rank, __func__,
387                        new simgrid::instr::CollTIData("allReduce", -1, 0,
388                                                       datatype->is_replayable() ? count : count * datatype->size(), -1,
389                                                       simgrid::smpi::Datatype::encode(datatype), ""));
390
391     simgrid::smpi::Colls::allreduce(sendtmpbuf, recvbuf, count, datatype, op, comm);
392
393     if( sendbuf == MPI_IN_PLACE )
394       xbt_free(sendtmpbuf);
395
396     retval = MPI_SUCCESS;
397     TRACE_smpi_comm_out(rank);
398   }
399
400   smpi_bench_begin();
401   return retval;
402 }
403
404 int PMPI_Scan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
405 {
406   int retval = 0;
407
408   smpi_bench_end();
409
410   if (comm == MPI_COMM_NULL) {
411     retval = MPI_ERR_COMM;
412   } else if (not datatype->is_valid()) {
413     retval = MPI_ERR_TYPE;
414   } else if (op == MPI_OP_NULL) {
415     retval = MPI_ERR_OP;
416   } else {
417     int rank = simgrid::s4u::this_actor::get_pid();
418     if (sendbuf == MPI_IN_PLACE) {
419       sendtmpbuf = static_cast<void*>(xbt_malloc(count * datatype->size()));
420       memcpy(sendtmpbuf, recvbuf, count * datatype->size());
421     }
422     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::Pt2PtTIData(
423                                            "scan", -1, datatype->is_replayable() ? count : count * datatype->size(),
424                                            simgrid::smpi::Datatype::encode(datatype)));
425
426     retval = simgrid::smpi::Colls::scan(sendtmpbuf, recvbuf, count, datatype, op, comm);
427
428     TRACE_smpi_comm_out(rank);
429     if (sendbuf == MPI_IN_PLACE)
430       xbt_free(sendtmpbuf);
431   }
432
433   smpi_bench_begin();
434   return retval;
435 }
436
437 int PMPI_Exscan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm){
438   int retval = 0;
439
440   smpi_bench_end();
441
442   if (comm == MPI_COMM_NULL) {
443     retval = MPI_ERR_COMM;
444   } else if (not datatype->is_valid()) {
445     retval = MPI_ERR_TYPE;
446   } else if (op == MPI_OP_NULL) {
447     retval = MPI_ERR_OP;
448   } else {
449     int rank         = simgrid::s4u::this_actor::get_pid();
450     void* sendtmpbuf = sendbuf;
451     if (sendbuf == MPI_IN_PLACE) {
452       sendtmpbuf = static_cast<void*>(xbt_malloc(count * datatype->size()));
453       memcpy(sendtmpbuf, recvbuf, count * datatype->size());
454     }
455
456     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::Pt2PtTIData(
457                                            "exscan", -1, datatype->is_replayable() ? count : count * datatype->size(),
458                                            simgrid::smpi::Datatype::encode(datatype)));
459
460     retval = simgrid::smpi::Colls::exscan(sendtmpbuf, recvbuf, count, datatype, op, comm);
461
462     TRACE_smpi_comm_out(rank);
463     if (sendbuf == MPI_IN_PLACE)
464       xbt_free(sendtmpbuf);
465   }
466
467   smpi_bench_begin();
468   return retval;
469 }
470
471 int PMPI_Reduce_scatter(void *sendbuf, void *recvbuf, int *recvcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
472 {
473   int retval = 0;
474   smpi_bench_end();
475
476   if (comm == MPI_COMM_NULL) {
477     retval = MPI_ERR_COMM;
478   } else if (not datatype->is_valid()) {
479     retval = MPI_ERR_TYPE;
480   } else if (op == MPI_OP_NULL) {
481     retval = MPI_ERR_OP;
482   } else if (recvcounts == nullptr) {
483     retval = MPI_ERR_ARG;
484   } else {
485     int rank                           = simgrid::s4u::this_actor::get_pid();
486     std::vector<int>* trace_recvcounts = new std::vector<int>;
487     int dt_send_size                   = datatype->is_replayable() ? 1 : datatype->size();
488     int totalcount    = 0;
489
490     for (int i = 0; i < comm->size(); i++) { // copy data to avoid bad free
491       trace_recvcounts->push_back(recvcounts[i] * dt_send_size);
492       totalcount += recvcounts[i];
493     }
494
495     void* sendtmpbuf = sendbuf;
496     if (sendbuf == MPI_IN_PLACE) {
497       sendtmpbuf = static_cast<void*>(xbt_malloc(totalcount * datatype->size()));
498       memcpy(sendtmpbuf, recvbuf, totalcount * datatype->size());
499     }
500
501     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::VarCollTIData(
502                                            "reduceScatter", -1, dt_send_size, nullptr, -1, trace_recvcounts,
503                                            simgrid::smpi::Datatype::encode(datatype), ""));
504
505     simgrid::smpi::Colls::reduce_scatter(sendtmpbuf, recvbuf, recvcounts, datatype, op, comm);
506     retval = MPI_SUCCESS;
507     TRACE_smpi_comm_out(rank);
508
509     if (sendbuf == MPI_IN_PLACE)
510       xbt_free(sendtmpbuf);
511   }
512
513   smpi_bench_begin();
514   return retval;
515 }
516
517 int PMPI_Reduce_scatter_block(void *sendbuf, void *recvbuf, int recvcount,
518                               MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
519 {
520   int retval;
521   smpi_bench_end();
522
523   if (comm == MPI_COMM_NULL) {
524     retval = MPI_ERR_COMM;
525   } else if (not datatype->is_valid()) {
526     retval = MPI_ERR_TYPE;
527   } else if (op == MPI_OP_NULL) {
528     retval = MPI_ERR_OP;
529   } else if (recvcount < 0) {
530     retval = MPI_ERR_ARG;
531   } else {
532     int count = comm->size();
533
534     int rank                           = simgrid::s4u::this_actor::get_pid();
535     int dt_send_size                   = datatype->is_replayable() ? 1 : datatype->size();
536     std::vector<int>* trace_recvcounts = new std::vector<int>(recvcount * dt_send_size); // copy data to avoid bad free
537
538     void* sendtmpbuf       = sendbuf;
539     if (sendbuf == MPI_IN_PLACE) {
540       sendtmpbuf = static_cast<void*>(xbt_malloc(recvcount * count * datatype->size()));
541       memcpy(sendtmpbuf, recvbuf, recvcount * count * datatype->size());
542     }
543
544     TRACE_smpi_comm_in(rank, __func__,
545                        new simgrid::instr::VarCollTIData("reduceScatter", -1, 0, nullptr, -1, trace_recvcounts,
546                                                          simgrid::smpi::Datatype::encode(datatype), ""));
547
548     int* recvcounts = new int[count];
549     for (int i      = 0; i < count; i++)
550       recvcounts[i] = recvcount;
551     simgrid::smpi::Colls::reduce_scatter(sendtmpbuf, recvbuf, recvcounts, datatype, op, comm);
552     delete[] recvcounts;
553     retval = MPI_SUCCESS;
554
555     TRACE_smpi_comm_out(rank);
556
557     if (sendbuf == MPI_IN_PLACE)
558       xbt_free(sendtmpbuf);
559   }
560
561   smpi_bench_begin();
562   return retval;
563 }
564
565 int PMPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
566                   MPI_Datatype recvtype, MPI_Comm comm)
567 {
568   int retval = 0;
569   smpi_bench_end();
570
571   if (comm == MPI_COMM_NULL) {
572     retval = MPI_ERR_COMM;
573   } else if ((sendbuf != MPI_IN_PLACE && sendtype == MPI_DATATYPE_NULL) || recvtype == MPI_DATATYPE_NULL) {
574     retval = MPI_ERR_TYPE;
575   } else {
576     int rank                 = simgrid::s4u::this_actor::get_pid();
577     void* sendtmpbuf         = static_cast<char*>(sendbuf);
578     int sendtmpcount         = sendcount;
579     MPI_Datatype sendtmptype = sendtype;
580     if (sendbuf == MPI_IN_PLACE) {
581       sendtmpbuf = static_cast<void*>(xbt_malloc(recvcount * comm->size() * recvtype->size()));
582       memcpy(sendtmpbuf, recvbuf, recvcount * comm->size() * recvtype->size());
583       sendtmpcount = recvcount;
584       sendtmptype  = recvtype;
585     }
586
587     TRACE_smpi_comm_in(rank, __func__,
588                        new simgrid::instr::CollTIData(
589                            "allToAll", -1, -1.0,
590                            sendtmptype->is_replayable() ? sendtmpcount : sendtmpcount * sendtmptype->size(),
591                            recvtype->is_replayable() ? recvcount : recvcount * recvtype->size(),
592                            simgrid::smpi::Datatype::encode(sendtmptype), simgrid::smpi::Datatype::encode(recvtype)));
593
594     retval = simgrid::smpi::Colls::alltoall(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcount, recvtype, comm);
595
596     TRACE_smpi_comm_out(rank);
597
598     if (sendbuf == MPI_IN_PLACE)
599       xbt_free(sendtmpbuf);
600   }
601
602   smpi_bench_begin();
603   return retval;
604 }
605
606 int PMPI_Alltoallv(void* sendbuf, int* sendcounts, int* senddisps, MPI_Datatype sendtype, void* recvbuf,
607                    int* recvcounts, int* recvdisps, MPI_Datatype recvtype, MPI_Comm comm)
608 {
609   int retval = 0;
610
611   smpi_bench_end();
612
613   if (comm == MPI_COMM_NULL) {
614     retval = MPI_ERR_COMM;
615   } else if (sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
616     retval = MPI_ERR_TYPE;
617   } else if ((sendbuf != MPI_IN_PLACE && (sendcounts == nullptr || senddisps == nullptr)) || recvcounts == nullptr ||
618              recvdisps == nullptr) {
619     retval = MPI_ERR_ARG;
620   } else {
621     int rank                           = simgrid::s4u::this_actor::get_pid();
622     int size               = comm->size();
623     int send_size                      = 0;
624     int recv_size                      = 0;
625     std::vector<int>* trace_sendcounts = new std::vector<int>;
626     std::vector<int>* trace_recvcounts = new std::vector<int>;
627     int dt_size_recv       = recvtype->size();
628
629     void* sendtmpbuf         = static_cast<char*>(sendbuf);
630     int* sendtmpcounts       = sendcounts;
631     int* sendtmpdisps        = senddisps;
632     MPI_Datatype sendtmptype = sendtype;
633     int maxsize              = 0;
634     for (int i = 0; i < size; i++) { // copy data to avoid bad free
635       recv_size += recvcounts[i] * dt_size_recv;
636       trace_recvcounts->push_back(recvcounts[i] * dt_size_recv);
637       if (((recvdisps[i] + recvcounts[i]) * dt_size_recv) > maxsize)
638         maxsize = (recvdisps[i] + recvcounts[i]) * dt_size_recv;
639     }
640
641     if (sendbuf == MPI_IN_PLACE) {
642       sendtmpbuf = static_cast<void*>(xbt_malloc(maxsize));
643       memcpy(sendtmpbuf, recvbuf, maxsize);
644       sendtmpcounts = static_cast<int*>(xbt_malloc(size * sizeof(int)));
645       memcpy(sendtmpcounts, recvcounts, size * sizeof(int));
646       sendtmpdisps = static_cast<int*>(xbt_malloc(size * sizeof(int)));
647       memcpy(sendtmpdisps, recvdisps, size * sizeof(int));
648       sendtmptype = recvtype;
649     }
650
651     int dt_size_send = sendtmptype->size();
652
653     for (int i = 0; i < size; i++) { // copy data to avoid bad free
654       send_size += sendtmpcounts[i] * dt_size_send;
655       trace_sendcounts->push_back(sendtmpcounts[i] * dt_size_send);
656     }
657
658     TRACE_smpi_comm_in(rank, __func__,
659                        new simgrid::instr::VarCollTIData("allToAllV", -1, send_size, trace_sendcounts, recv_size,
660                                                          trace_recvcounts, simgrid::smpi::Datatype::encode(sendtype),
661                                                          simgrid::smpi::Datatype::encode(recvtype)));
662
663     retval = simgrid::smpi::Colls::alltoallv(sendtmpbuf, sendtmpcounts, sendtmpdisps, sendtmptype, recvbuf, recvcounts,
664                                     recvdisps, recvtype, comm);
665     TRACE_smpi_comm_out(rank);
666
667     if (sendbuf == MPI_IN_PLACE) {
668       xbt_free(sendtmpbuf);
669       xbt_free(sendtmpcounts);
670       xbt_free(sendtmpdisps);
671     }
672   }
673
674   smpi_bench_begin();
675   return retval;
676 }