Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
prefer this_actor:: to Actor::self()->
[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::getPid();
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::getPid();
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::getPid();
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 (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::getPid();
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::getPid();
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::getPid();
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::getPid();
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::getPid();
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::getPid();
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::getPid();
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::getPid();
418
419     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::Pt2PtTIData(
420                                            "scan", -1, datatype->is_replayable() ? count : count * datatype->size(),
421                                            simgrid::smpi::Datatype::encode(datatype)));
422
423     retval = simgrid::smpi::Colls::scan(sendbuf, recvbuf, count, datatype, op, comm);
424
425     TRACE_smpi_comm_out(rank);
426   }
427
428   smpi_bench_begin();
429   return retval;
430 }
431
432 int PMPI_Exscan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm){
433   int retval = 0;
434
435   smpi_bench_end();
436
437   if (comm == MPI_COMM_NULL) {
438     retval = MPI_ERR_COMM;
439   } else if (not datatype->is_valid()) {
440     retval = MPI_ERR_TYPE;
441   } else if (op == MPI_OP_NULL) {
442     retval = MPI_ERR_OP;
443   } else {
444     int rank         = simgrid::s4u::this_actor::getPid();
445     void* sendtmpbuf = sendbuf;
446     if (sendbuf == MPI_IN_PLACE) {
447       sendtmpbuf = static_cast<void*>(xbt_malloc(count * datatype->size()));
448       memcpy(sendtmpbuf, recvbuf, count * datatype->size());
449     }
450
451     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::Pt2PtTIData(
452                                            "exscan", -1, datatype->is_replayable() ? count : count * datatype->size(),
453                                            simgrid::smpi::Datatype::encode(datatype)));
454
455     retval = simgrid::smpi::Colls::exscan(sendtmpbuf, recvbuf, count, datatype, op, comm);
456
457     TRACE_smpi_comm_out(rank);
458     if (sendbuf == MPI_IN_PLACE)
459       xbt_free(sendtmpbuf);
460   }
461
462   smpi_bench_begin();
463   return retval;
464 }
465
466 int PMPI_Reduce_scatter(void *sendbuf, void *recvbuf, int *recvcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
467 {
468   int retval = 0;
469   smpi_bench_end();
470
471   if (comm == MPI_COMM_NULL) {
472     retval = MPI_ERR_COMM;
473   } else if (not datatype->is_valid()) {
474     retval = MPI_ERR_TYPE;
475   } else if (op == MPI_OP_NULL) {
476     retval = MPI_ERR_OP;
477   } else if (recvcounts == nullptr) {
478     retval = MPI_ERR_ARG;
479   } else {
480     int rank                           = simgrid::s4u::this_actor::getPid();
481     std::vector<int>* trace_recvcounts = new std::vector<int>;
482     int dt_send_size                   = datatype->is_replayable() ? 1 : datatype->size();
483     int totalcount    = 0;
484
485     for (int i = 0; i < comm->size(); i++) { // copy data to avoid bad free
486       trace_recvcounts->push_back(recvcounts[i] * dt_send_size);
487       totalcount += recvcounts[i];
488     }
489
490     void* sendtmpbuf = sendbuf;
491     if (sendbuf == MPI_IN_PLACE) {
492       sendtmpbuf = static_cast<void*>(xbt_malloc(totalcount * datatype->size()));
493       memcpy(sendtmpbuf, recvbuf, totalcount * datatype->size());
494     }
495
496     TRACE_smpi_comm_in(rank, __func__, new simgrid::instr::VarCollTIData(
497                                            "reduceScatter", -1, dt_send_size, nullptr, -1, trace_recvcounts,
498                                            simgrid::smpi::Datatype::encode(datatype), ""));
499
500     simgrid::smpi::Colls::reduce_scatter(sendtmpbuf, recvbuf, recvcounts, datatype, op, comm);
501     retval = MPI_SUCCESS;
502     TRACE_smpi_comm_out(rank);
503
504     if (sendbuf == MPI_IN_PLACE)
505       xbt_free(sendtmpbuf);
506   }
507
508   smpi_bench_begin();
509   return retval;
510 }
511
512 int PMPI_Reduce_scatter_block(void *sendbuf, void *recvbuf, int recvcount,
513                               MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
514 {
515   int retval;
516   smpi_bench_end();
517
518   if (comm == MPI_COMM_NULL) {
519     retval = MPI_ERR_COMM;
520   } else if (not datatype->is_valid()) {
521     retval = MPI_ERR_TYPE;
522   } else if (op == MPI_OP_NULL) {
523     retval = MPI_ERR_OP;
524   } else if (recvcount < 0) {
525     retval = MPI_ERR_ARG;
526   } else {
527     int count = comm->size();
528
529     int rank                           = simgrid::s4u::this_actor::getPid();
530     int dt_send_size                   = datatype->is_replayable() ? 1 : datatype->size();
531     std::vector<int>* trace_recvcounts = new std::vector<int>(recvcount * dt_send_size); // copy data to avoid bad free
532
533     void* sendtmpbuf       = sendbuf;
534     if (sendbuf == MPI_IN_PLACE) {
535       sendtmpbuf = static_cast<void*>(xbt_malloc(recvcount * count * datatype->size()));
536       memcpy(sendtmpbuf, recvbuf, recvcount * count * datatype->size());
537     }
538
539     TRACE_smpi_comm_in(rank, __func__,
540                        new simgrid::instr::VarCollTIData("reduceScatter", -1, 0, nullptr, -1, trace_recvcounts,
541                                                          simgrid::smpi::Datatype::encode(datatype), ""));
542
543     int* recvcounts = new int[count];
544     for (int i      = 0; i < count; i++)
545       recvcounts[i] = recvcount;
546     simgrid::smpi::Colls::reduce_scatter(sendtmpbuf, recvbuf, recvcounts, datatype, op, comm);
547     delete[] recvcounts;
548     retval = MPI_SUCCESS;
549
550     TRACE_smpi_comm_out(rank);
551
552     if (sendbuf == MPI_IN_PLACE)
553       xbt_free(sendtmpbuf);
554   }
555
556   smpi_bench_begin();
557   return retval;
558 }
559
560 int PMPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
561                   MPI_Datatype recvtype, MPI_Comm comm)
562 {
563   int retval = 0;
564   smpi_bench_end();
565
566   if (comm == MPI_COMM_NULL) {
567     retval = MPI_ERR_COMM;
568   } else if ((sendbuf != MPI_IN_PLACE && sendtype == MPI_DATATYPE_NULL) || recvtype == MPI_DATATYPE_NULL) {
569     retval = MPI_ERR_TYPE;
570   } else {
571     int rank                 = simgrid::s4u::this_actor::getPid();
572     void* sendtmpbuf         = static_cast<char*>(sendbuf);
573     int sendtmpcount         = sendcount;
574     MPI_Datatype sendtmptype = sendtype;
575     if (sendbuf == MPI_IN_PLACE) {
576       sendtmpbuf = static_cast<void*>(xbt_malloc(recvcount * comm->size() * recvtype->size()));
577       memcpy(sendtmpbuf, recvbuf, recvcount * comm->size() * recvtype->size());
578       sendtmpcount = recvcount;
579       sendtmptype  = recvtype;
580     }
581
582     TRACE_smpi_comm_in(rank, __func__,
583                        new simgrid::instr::CollTIData(
584                            "allToAll", -1, -1.0,
585                            sendtmptype->is_replayable() ? sendtmpcount : sendtmpcount * sendtmptype->size(),
586                            recvtype->is_replayable() ? recvcount : recvcount * recvtype->size(),
587                            simgrid::smpi::Datatype::encode(sendtmptype), simgrid::smpi::Datatype::encode(recvtype)));
588
589     retval = simgrid::smpi::Colls::alltoall(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcount, recvtype, comm);
590
591     TRACE_smpi_comm_out(rank);
592
593     if (sendbuf == MPI_IN_PLACE)
594       xbt_free(sendtmpbuf);
595   }
596
597   smpi_bench_begin();
598   return retval;
599 }
600
601 int PMPI_Alltoallv(void* sendbuf, int* sendcounts, int* senddisps, MPI_Datatype sendtype, void* recvbuf,
602                    int* recvcounts, int* recvdisps, MPI_Datatype recvtype, MPI_Comm comm)
603 {
604   int retval = 0;
605
606   smpi_bench_end();
607
608   if (comm == MPI_COMM_NULL) {
609     retval = MPI_ERR_COMM;
610   } else if (sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
611     retval = MPI_ERR_TYPE;
612   } else if ((sendbuf != MPI_IN_PLACE && (sendcounts == nullptr || senddisps == nullptr)) || recvcounts == nullptr ||
613              recvdisps == nullptr) {
614     retval = MPI_ERR_ARG;
615   } else {
616     int rank                           = simgrid::s4u::this_actor::getPid();
617     int size               = comm->size();
618     int send_size                      = 0;
619     int recv_size                      = 0;
620     std::vector<int>* trace_sendcounts = new std::vector<int>;
621     std::vector<int>* trace_recvcounts = new std::vector<int>;
622     int dt_size_recv       = recvtype->size();
623
624     void* sendtmpbuf         = static_cast<char*>(sendbuf);
625     int* sendtmpcounts       = sendcounts;
626     int* sendtmpdisps        = senddisps;
627     MPI_Datatype sendtmptype = sendtype;
628     int maxsize              = 0;
629     for (int i = 0; i < size; i++) { // copy data to avoid bad free
630       recv_size += recvcounts[i] * dt_size_recv;
631       trace_recvcounts->push_back(recvcounts[i] * dt_size_recv);
632       if (((recvdisps[i] + recvcounts[i]) * dt_size_recv) > maxsize)
633         maxsize = (recvdisps[i] + recvcounts[i]) * dt_size_recv;
634     }
635
636     if (sendbuf == MPI_IN_PLACE) {
637       sendtmpbuf = static_cast<void*>(xbt_malloc(maxsize));
638       memcpy(sendtmpbuf, recvbuf, maxsize);
639       sendtmpcounts = static_cast<int*>(xbt_malloc(size * sizeof(int)));
640       memcpy(sendtmpcounts, recvcounts, size * sizeof(int));
641       sendtmpdisps = static_cast<int*>(xbt_malloc(size * sizeof(int)));
642       memcpy(sendtmpdisps, recvdisps, size * sizeof(int));
643       sendtmptype = recvtype;
644     }
645
646     int dt_size_send = sendtmptype->size();
647
648     for (int i = 0; i < size; i++) { // copy data to avoid bad free
649       send_size += sendtmpcounts[i] * dt_size_send;
650       trace_sendcounts->push_back(sendtmpcounts[i] * dt_size_send);
651     }
652
653     TRACE_smpi_comm_in(rank, __func__,
654                        new simgrid::instr::VarCollTIData("allToAllV", -1, send_size, trace_sendcounts, recv_size,
655                                                          trace_recvcounts, simgrid::smpi::Datatype::encode(sendtype),
656                                                          simgrid::smpi::Datatype::encode(recvtype)));
657
658     retval = simgrid::smpi::Colls::alltoallv(sendtmpbuf, sendtmpcounts, sendtmpdisps, sendtmptype, recvbuf, recvcounts,
659                                     recvdisps, recvtype, comm);
660     TRACE_smpi_comm_out(rank);
661
662     if (sendbuf == MPI_IN_PLACE) {
663       xbt_free(sendtmpbuf);
664       xbt_free(sendtmpcounts);
665       xbt_free(sendtmpdisps);
666     }
667   }
668
669   smpi_bench_begin();
670   return retval;
671 }