1 /* Copyright (c) 2009, 2010, 2011, 2012. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include <xbt/replay.h>
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_replay,smpi,"Trace Replay with SMPI");
15 int communicator_size = 0;
16 static int active_processes = 0;
17 xbt_dynar_t *reqq = NULL;
19 MPI_Datatype MPI_DEFAULT_TYPE;
20 MPI_Datatype MPI_CURRENT_TYPE;
22 static void log_timed_action (const char *const *action, double clock){
23 if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){
24 char *name = xbt_str_join_array(action, " ");
25 XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock);
31 xbt_dynar_t isends; /* of MPI_Request */
32 xbt_dynar_t irecvs; /* of MPI_Request */
33 } s_smpi_replay_globals_t, *smpi_replay_globals_t;
37 static double parse_double(const char *string)
41 value = strtod(string, &endptr);
43 THROWF(unknown_error, 0, "%s is not a double", string);
47 static MPI_Datatype decode_datatype(const char *const action)
49 // Declared datatypes,
54 MPI_CURRENT_TYPE=MPI_DOUBLE;
57 MPI_CURRENT_TYPE=MPI_INT;
60 MPI_CURRENT_TYPE=MPI_CHAR;
63 MPI_CURRENT_TYPE=MPI_SHORT;
66 MPI_CURRENT_TYPE=MPI_LONG;
69 MPI_CURRENT_TYPE=MPI_FLOAT;
72 MPI_CURRENT_TYPE=MPI_BYTE;
75 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
78 return MPI_CURRENT_TYPE;
81 static void action_init(const char *const *action)
84 XBT_DEBUG("Initialize the counters");
85 smpi_replay_globals_t globals = xbt_new(s_smpi_replay_globals_t, 1);
86 globals->isends = xbt_dynar_new(sizeof(MPI_Request),NULL);
87 globals->irecvs = xbt_dynar_new(sizeof(MPI_Request),NULL);
89 if(action[2]) MPI_DEFAULT_TYPE= MPI_DOUBLE; // default MPE dataype
90 else MPI_DEFAULT_TYPE= MPI_BYTE; // default TAU datatype
92 smpi_process_set_user_data((void*) globals);
94 /* start a simulated timer */
95 smpi_process_simulated_start();
96 /*initialize the number of active processes */
97 active_processes = smpi_process_count();
100 reqq=xbt_new0(xbt_dynar_t,active_processes);
102 for(i=0;i<active_processes;i++){
103 reqq[i]=xbt_dynar_new(sizeof(MPI_Request),NULL);
108 static void action_finalize(const char *const *action)
110 smpi_replay_globals_t globals =
111 (smpi_replay_globals_t) smpi_process_get_user_data();
113 XBT_DEBUG("There are %lu isends and %lu irecvs in the dynars",
114 xbt_dynar_length(globals->isends),xbt_dynar_length(globals->irecvs));
115 xbt_dynar_free_container(&(globals->isends));
116 xbt_dynar_free_container(&(globals->irecvs));
121 static void action_comm_size(const char *const *action)
123 double clock = smpi_process_simulated_elapsed();
125 communicator_size = parse_double(action[2]);
126 log_timed_action (action, clock);
129 static void action_comm_split(const char *const *action)
131 double clock = smpi_process_simulated_elapsed();
133 log_timed_action (action, clock);
136 static void action_comm_dup(const char *const *action)
138 double clock = smpi_process_simulated_elapsed();
140 log_timed_action (action, clock);
143 static void action_compute(const char *const *action)
145 double clock = smpi_process_simulated_elapsed();
146 smpi_execute_flops(parse_double(action[2]));
148 log_timed_action (action, clock);
151 static void action_send(const char *const *action)
153 int to = atoi(action[2]);
154 double size=parse_double(action[3]);
155 double clock = smpi_process_simulated_elapsed();
158 MPI_CURRENT_TYPE=decode_datatype(action[4]);
160 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
164 int rank = smpi_comm_rank(MPI_COMM_WORLD);
165 TRACE_smpi_computing_out(rank);
166 int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to);
167 TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__);
168 TRACE_smpi_send(rank, rank, dst_traced);
171 smpi_mpi_send(NULL, size, MPI_CURRENT_TYPE, to , 0, MPI_COMM_WORLD);
173 log_timed_action (action, clock);
176 TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
177 TRACE_smpi_computing_in(rank);
182 static void action_Isend(const char *const *action)
184 int to = atoi(action[2]);
185 double size=parse_double(action[3]);
186 double clock = smpi_process_simulated_elapsed();
189 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
190 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
192 smpi_replay_globals_t globals =
193 (smpi_replay_globals_t) smpi_process_get_user_data();
195 int rank = smpi_comm_rank(MPI_COMM_WORLD);
196 TRACE_smpi_computing_out(rank);
197 int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to);
198 TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__);
199 TRACE_smpi_send(rank, rank, dst_traced);
202 request = smpi_mpi_isend(NULL, size, MPI_CURRENT_TYPE, to, 0,MPI_COMM_WORLD);
205 TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
207 TRACE_smpi_computing_in(rank);
210 xbt_dynar_push(globals->isends,&request);
211 xbt_dynar_push(reqq[smpi_comm_rank(MPI_COMM_WORLD)],&request);
213 log_timed_action (action, clock);
216 static void action_recv(const char *const *action) {
217 int from = atoi(action[2]);
218 double size=parse_double(action[3]);
219 double clock = smpi_process_simulated_elapsed();
222 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
223 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
226 int rank = smpi_comm_rank(MPI_COMM_WORLD);
227 int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from);
228 TRACE_smpi_computing_out(rank);
230 TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__);
233 smpi_mpi_recv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD, &status);
236 TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
237 TRACE_smpi_recv(rank, src_traced, rank);
238 TRACE_smpi_computing_in(rank);
241 log_timed_action (action, clock);
244 static void action_Irecv(const char *const *action)
246 int from = atoi(action[2]);
247 double size=parse_double(action[3]);
248 double clock = smpi_process_simulated_elapsed();
251 smpi_replay_globals_t globals =
252 (smpi_replay_globals_t) smpi_process_get_user_data();
254 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
255 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
258 int rank = smpi_comm_rank(MPI_COMM_WORLD);
259 int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from);
260 TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__);
263 request = smpi_mpi_irecv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD);
266 TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
269 xbt_dynar_push(globals->irecvs,&request);
270 xbt_dynar_push(reqq[smpi_comm_rank(MPI_COMM_WORLD)],&request);
272 log_timed_action (action, clock);
275 static void action_wait(const char *const *action){
276 double clock = smpi_process_simulated_elapsed();
279 smpi_replay_globals_t globals =
280 (smpi_replay_globals_t) smpi_process_get_user_data();
282 xbt_assert(xbt_dynar_length(globals->irecvs),
283 "action wait not preceded by any irecv: %s",
284 xbt_str_join_array(action," "));
285 request = xbt_dynar_pop_as(globals->irecvs,MPI_Request);
287 int rank = request && request->comm != MPI_COMM_NULL
288 ? smpi_comm_rank(request->comm)
290 TRACE_smpi_computing_out(rank);
292 MPI_Group group = smpi_comm_group(request->comm);
293 int src_traced = smpi_group_rank(group, request->src);
294 int dst_traced = smpi_group_rank(group, request->dst);
295 int is_wait_for_receive = request->recv;
296 TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__);
298 smpi_mpi_wait(&request, &status);
300 TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
301 if (is_wait_for_receive) {
302 TRACE_smpi_recv(rank, src_traced, dst_traced);
304 TRACE_smpi_computing_in(rank);
307 log_timed_action (action, clock);
310 static void action_waitall(const char *const *action){
311 double clock = smpi_process_simulated_elapsed();
312 int count_requests=0;
315 count_requests=xbt_dynar_length(reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
317 if (count_requests>0) {
318 MPI_Request requests[count_requests];
319 MPI_Status status[count_requests];
321 /* The reqq is an array of dynars. Its index corresponds to the rank.
322 Thus each rank saves its own requests to the array request. */
323 xbt_dynar_foreach(reqq[smpi_comm_rank(MPI_COMM_WORLD)],i,requests[i]);
326 //save information from requests
328 xbt_dynar_t srcs = xbt_dynar_new(sizeof(int), NULL);
329 xbt_dynar_t dsts = xbt_dynar_new(sizeof(int), NULL);
330 xbt_dynar_t recvs = xbt_dynar_new(sizeof(int), NULL);
331 for (i = 0; i < count_requests; i++) {
333 int *asrc = xbt_new(int, 1);
334 int *adst = xbt_new(int, 1);
335 int *arecv = xbt_new(int, 1);
336 *asrc = requests[i]->src;
337 *adst = requests[i]->dst;
338 *arecv = requests[i]->recv;
339 xbt_dynar_insert_at(srcs, i, asrc);
340 xbt_dynar_insert_at(dsts, i, adst);
341 xbt_dynar_insert_at(recvs, i, arecv);
346 int *t = xbt_new(int, 1);
347 xbt_dynar_insert_at(srcs, i, t);
348 xbt_dynar_insert_at(dsts, i, t);
349 xbt_dynar_insert_at(recvs, i, t);
353 int rank_traced = smpi_process_index();
354 TRACE_smpi_computing_out(rank_traced);
356 TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__);
359 smpi_mpi_waitall(count_requests, requests, status);
362 for (i = 0; i < count_requests; i++) {
363 int src_traced, dst_traced, is_wait_for_receive;
364 xbt_dynar_get_cpy(srcs, i, &src_traced);
365 xbt_dynar_get_cpy(dsts, i, &dst_traced);
366 xbt_dynar_get_cpy(recvs, i, &is_wait_for_receive);
367 if (is_wait_for_receive) {
368 TRACE_smpi_recv(rank_traced, src_traced, dst_traced);
371 TRACE_smpi_ptp_out(rank_traced, -1, -1, __FUNCTION__);
373 xbt_dynar_free(&srcs);
374 xbt_dynar_free(&dsts);
375 xbt_dynar_free(&recvs);
376 TRACE_smpi_computing_in(rank_traced);
379 xbt_dynar_reset(reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
381 log_timed_action (action, clock);
384 static void action_barrier(const char *const *action){
385 double clock = smpi_process_simulated_elapsed();
387 int rank = smpi_comm_rank(MPI_COMM_WORLD);
388 TRACE_smpi_computing_out(rank);
389 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
391 smpi_mpi_barrier(MPI_COMM_WORLD);
393 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
394 TRACE_smpi_computing_in(rank);
397 log_timed_action (action, clock);
401 static void action_bcast(const char *const *action)
403 double size = parse_double(action[2]);
404 double clock = smpi_process_simulated_elapsed();
407 * Initialize MPI_CURRENT_TYPE in order to decrease
408 * the number of the checks
410 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
413 root= atoi(action[3]);
415 MPI_CURRENT_TYPE=decode_datatype(action[4]);
420 int rank = smpi_comm_rank(MPI_COMM_WORLD);
421 TRACE_smpi_computing_out(rank);
422 int root_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), 0);
423 TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
426 smpi_mpi_bcast(NULL, size, MPI_CURRENT_TYPE, root, MPI_COMM_WORLD);
428 TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
429 TRACE_smpi_computing_in(rank);
432 log_timed_action (action, clock);
435 static void action_reduce(const char *const *action)
437 double comm_size = parse_double(action[2]);
438 double comp_size = parse_double(action[3]);
439 double clock = smpi_process_simulated_elapsed();
441 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
444 root= atoi(action[4]);
446 MPI_CURRENT_TYPE=decode_datatype(action[5]);
451 int rank = smpi_comm_rank(MPI_COMM_WORLD);
452 TRACE_smpi_computing_out(rank);
453 int root_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), 0);
454 TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
456 mpi_coll_reduce_fun(NULL, NULL, comm_size, MPI_CURRENT_TYPE, MPI_OP_NULL, root, MPI_COMM_WORLD);
457 smpi_execute_flops(comp_size);
459 TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
460 TRACE_smpi_computing_in(rank);
463 log_timed_action (action, clock);
466 static void action_allReduce(const char *const *action) {
467 double comm_size = parse_double(action[2]);
468 double comp_size = parse_double(action[3]);
470 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
471 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
473 double clock = smpi_process_simulated_elapsed();
475 int rank = smpi_comm_rank(MPI_COMM_WORLD);
476 TRACE_smpi_computing_out(rank);
477 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
479 mpi_coll_reduce_fun(NULL, NULL, comm_size, MPI_CURRENT_TYPE, MPI_OP_NULL, 0, MPI_COMM_WORLD);
480 smpi_execute_flops(comp_size);
481 mpi_coll_bcast_fun(NULL, comm_size, MPI_CURRENT_TYPE, 0, MPI_COMM_WORLD);
483 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
484 TRACE_smpi_computing_in(rank);
487 log_timed_action (action, clock);
490 static void action_allToAll(const char *const *action) {
491 double clock = smpi_process_simulated_elapsed();
492 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
493 int send_size = parse_double(action[2]);
494 int recv_size = parse_double(action[3]);
495 MPI_Datatype MPI_CURRENT_TYPE2;
498 MPI_CURRENT_TYPE=decode_datatype(action[4]);
499 MPI_CURRENT_TYPE2=decode_datatype(action[5]);
502 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
503 MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
505 void *send = calloc(send_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE));
506 void *recv = calloc(recv_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
509 int rank = smpi_process_index();
510 TRACE_smpi_computing_out(rank);
511 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
514 mpi_coll_alltoall_fun(send, send_size, MPI_CURRENT_TYPE, recv, recv_size, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
517 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
518 TRACE_smpi_computing_in(rank);
521 log_timed_action (action, clock);
527 static void action_gather(const char *const *action) {
531 The structure of the gather action for the rank 0 (total 4 processes)
536 1) 68 is the sendcounts
537 2) 68 is the recvcounts
538 3) 0 is the root node
539 4) 0 is the send datatype id, see decode_datatype()
540 5) 0 is the recv datatype id, see decode_datatype()
543 double clock = smpi_process_simulated_elapsed();
544 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
545 int send_size = parse_double(action[2]);
546 int recv_size = parse_double(action[3]);
547 MPI_Datatype MPI_CURRENT_TYPE2;
549 MPI_CURRENT_TYPE=decode_datatype(action[5]);
550 MPI_CURRENT_TYPE2=decode_datatype(action[6]);
552 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
553 MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
555 void *send = calloc(send_size, smpi_datatype_size(MPI_CURRENT_TYPE));
556 void *recv = calloc(recv_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
558 int root=atoi(action[4]);
559 int rank = smpi_process_index();
562 recv = calloc(recv_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
565 TRACE_smpi_computing_out(rank);
566 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
568 smpi_mpi_gather(send, send_size, MPI_CURRENT_TYPE,
569 recv, recv_size, MPI_CURRENT_TYPE2,
570 root, MPI_COMM_WORLD);
573 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
574 TRACE_smpi_computing_in(rank);
577 log_timed_action (action, clock);
583 static void action_reducescatter(const char *const *action) {
586 The structure of the reducescatter action for the rank 0 (total 4 processes)
588 0 reduceScatter 275427 275427 275427 204020 11346849 0
591 1) The first four values after the name of the action declare the recvcounts array
592 2) The value 11346849 is the amount of instructions
593 3) The last value corresponds to the datatype, see decode_datatype().
595 We analyze a MPI_Reduce_scatter call to one MPI_Reduce and one MPI_Scatterv.
599 double clock = smpi_process_simulated_elapsed();
600 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
601 int comp_size = parse_double(action[2+comm_size]);
602 int *recvcounts = xbt_new0(int, comm_size);
603 int *disps = xbt_new0(int, comm_size);
606 int rank = smpi_process_index();
608 if(action[3+comm_size])
609 MPI_CURRENT_TYPE=decode_datatype(action[3+comm_size]);
611 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
613 for(i=0;i<comm_size;i++) {
614 recvcounts[i] = atoi(action[i+2]);
615 recv_sum=recv_sum+recvcounts[i];
620 TRACE_smpi_computing_out(rank);
621 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
623 mpi_coll_reduce_fun(NULL, NULL, recv_sum, MPI_CURRENT_TYPE, MPI_OP_NULL,
624 root, MPI_COMM_WORLD);
625 smpi_mpi_scatterv(NULL, recvcounts, disps, MPI_CURRENT_TYPE, NULL,
626 recvcounts[rank], MPI_CURRENT_TYPE, 0, MPI_COMM_WORLD);
627 smpi_execute_flops(comp_size);
631 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
632 TRACE_smpi_computing_in(rank);
635 log_timed_action (action, clock);
639 static void action_allgatherv(const char *const *action) {
642 The structure of the allgatherv action for the rank 0 (total 4 processes)
644 0 allGatherV 275427 275427 275427 275427 204020 0 275427 550854 826281
647 1) 275427 is the sendcount
648 2) The next four elements declare the recvcounts array
649 3) The next four values declare the disps array
650 4) No more values mean that the datatype for sent and receive buffer
651 is the default one, see decode_datatype().
655 double clock = smpi_process_simulated_elapsed();
657 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
659 int sendcount=atoi(action[2]);
660 int *recvcounts = xbt_new0(int, comm_size);
661 int *disps = xbt_new0(int, comm_size);
663 MPI_Datatype MPI_CURRENT_TYPE2;
665 if(action[3+2*comm_size]) {
666 MPI_CURRENT_TYPE = decode_datatype(action[3+2*comm_size]);
667 MPI_CURRENT_TYPE2 = decode_datatype(action[4+2*comm_size]);
669 MPI_CURRENT_TYPE = MPI_DEFAULT_TYPE;
670 MPI_CURRENT_TYPE2 = MPI_DEFAULT_TYPE;
672 void *sendbuf = calloc(sendcount, smpi_datatype_size(MPI_CURRENT_TYPE));
674 for(i=0;i<comm_size;i++) {
675 recvcounts[i] = atoi(action[i+3]);
676 recv_sum=recv_sum+recvcounts[i];
677 disps[i] = atoi(action[i+3+comm_size]);
679 void *recvbuf = calloc(recv_sum, smpi_datatype_size(MPI_CURRENT_TYPE2));
682 int rank = MPI_COMM_WORLD != MPI_COMM_NULL ? smpi_process_index() : -1;
683 TRACE_smpi_computing_out(rank);
684 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
687 mpi_coll_allgatherv_fun(sendbuf, sendcount, MPI_CURRENT_TYPE, recvbuf, recvcounts, disps, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
690 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
691 TRACE_smpi_computing_in(rank);
694 log_timed_action (action, clock);
697 xbt_free(recvcounts);
702 static void action_allToAllv(const char *const *action) {
704 The structure of the allToAllV action for the rank 0 (total 4 processes)
706 0 allToAllV 100 1 7 10 12 5 10 20 45 100 1 70 10 5 1 5 77 90
709 1) 100 is the size of the send buffer *sizeof(int),
710 2) 1 7 10 12 is the sendcounts array
711 3) 5 10 20 45 is the sdispls array
712 4) 100*sizeof(int) is the size of the receiver buffer
713 5) 1 70 10 5 is the recvcounts array
714 6) 1 5 77 90 is the rdispls array
719 double clock = smpi_process_simulated_elapsed();
721 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
722 int send_buf_size=0,recv_buf_size=0,i=0;
723 int *sendcounts = xbt_new0(int, comm_size);
724 int *recvcounts = xbt_new0(int, comm_size);
725 int *senddisps = xbt_new0(int, comm_size);
726 int *recvdisps = xbt_new0(int, comm_size);
728 MPI_Datatype MPI_CURRENT_TYPE2;
730 send_buf_size=parse_double(action[2]);
731 recv_buf_size=parse_double(action[3+2*comm_size]);
732 if(action[4+4*comm_size]) {
733 MPI_CURRENT_TYPE=decode_datatype(action[4+4*comm_size]);
734 MPI_CURRENT_TYPE2=decode_datatype(action[5+4*comm_size]);
737 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
738 MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
741 void *sendbuf = calloc(send_buf_size, smpi_datatype_size(MPI_CURRENT_TYPE));
742 void *recvbuf = calloc(recv_buf_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
744 for(i=0;i<comm_size;i++) {
745 sendcounts[i] = atoi(action[i+3]);
746 senddisps[i] = atoi(action[i+3+comm_size]);
747 recvcounts[i] = atoi(action[i+4+2*comm_size]);
748 recvdisps[i] = atoi(action[i+4+3*comm_size]);
753 int rank = MPI_COMM_WORLD != MPI_COMM_NULL ? smpi_process_index() : -1;
754 TRACE_smpi_computing_out(rank);
755 TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
757 mpi_coll_alltoallv_fun(sendbuf, sendcounts, senddisps, MPI_CURRENT_TYPE,
758 recvbuf, recvcounts, recvdisps, MPI_CURRENT_TYPE,
761 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
762 TRACE_smpi_computing_in(rank);
765 log_timed_action (action, clock);
768 xbt_free(sendcounts);
769 xbt_free(recvcounts);
776 void smpi_replay_init(int *argc, char***argv){
777 PMPI_Init(argc, argv);
778 if (!smpi_process_index()){
779 _xbt_replay_action_init();
780 xbt_replay_action_register("init", action_init);
781 xbt_replay_action_register("finalize", action_finalize);
782 xbt_replay_action_register("comm_size", action_comm_size);
783 xbt_replay_action_register("comm_split", action_comm_split);
784 xbt_replay_action_register("comm_dup", action_comm_dup);
785 xbt_replay_action_register("send", action_send);
786 xbt_replay_action_register("Isend", action_Isend);
787 xbt_replay_action_register("recv", action_recv);
788 xbt_replay_action_register("Irecv", action_Irecv);
789 xbt_replay_action_register("wait", action_wait);
790 xbt_replay_action_register("waitAll", action_waitall);
791 xbt_replay_action_register("barrier", action_barrier);
792 xbt_replay_action_register("bcast", action_bcast);
793 xbt_replay_action_register("reduce", action_reduce);
794 xbt_replay_action_register("allReduce", action_allReduce);
795 xbt_replay_action_register("allToAll", action_allToAll);
796 xbt_replay_action_register("allToAllV", action_allToAllv);
797 xbt_replay_action_register("gather", action_gather);
798 xbt_replay_action_register("allGatherV", action_allgatherv);
799 xbt_replay_action_register("reduceScatter", action_reducescatter);
800 xbt_replay_action_register("compute", action_compute);
803 xbt_replay_action_runner(*argc, *argv);
806 int smpi_replay_finalize(){
808 /* One active process will stop. Decrease the counter*/
810 XBT_DEBUG("There are %lu elements in reqq[*]",
811 xbt_dynar_length(reqq[smpi_comm_rank(MPI_COMM_WORLD)]));
812 xbt_dynar_free(&reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
813 if(!active_processes){
814 /* Last process alive speaking */
815 /* end the simulated timer */
816 sim_time = smpi_process_simulated_elapsed();
817 XBT_INFO("Simulation time %g", sim_time);
818 _xbt_replay_action_exit();
822 smpi_mpi_barrier(MPI_COMM_WORLD);
823 return PMPI_Finalize();