1 /* Copyright (c) 2009-2013. 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 irecvs; /* of MPI_Request */
32 } s_smpi_replay_globals_t, *smpi_replay_globals_t;
36 static double parse_double(const char *string)
40 value = strtod(string, &endptr);
42 THROWF(unknown_error, 0, "%s is not a double", string);
46 static MPI_Datatype decode_datatype(const char *const action)
48 // Declared datatypes,
53 MPI_CURRENT_TYPE=MPI_DOUBLE;
56 MPI_CURRENT_TYPE=MPI_INT;
59 MPI_CURRENT_TYPE=MPI_CHAR;
62 MPI_CURRENT_TYPE=MPI_SHORT;
65 MPI_CURRENT_TYPE=MPI_LONG;
68 MPI_CURRENT_TYPE=MPI_FLOAT;
71 MPI_CURRENT_TYPE=MPI_BYTE;
74 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
77 return MPI_CURRENT_TYPE;
80 static void action_init(const char *const *action)
83 XBT_DEBUG("Initialize the counters");
84 smpi_replay_globals_t globals = xbt_new(s_smpi_replay_globals_t, 1);
85 globals->irecvs = xbt_dynar_new(sizeof(MPI_Request),NULL);
87 if(action[2]) MPI_DEFAULT_TYPE= MPI_DOUBLE; // default MPE dataype
88 else MPI_DEFAULT_TYPE= MPI_BYTE; // default TAU datatype
90 smpi_process_set_user_data((void*) globals);
92 /* start a simulated timer */
93 smpi_process_simulated_start();
94 /*initialize the number of active processes */
95 active_processes = smpi_process_count();
98 reqq=xbt_new0(xbt_dynar_t,active_processes);
100 for(i=0;i<active_processes;i++){
101 reqq[i]=xbt_dynar_new(sizeof(MPI_Request),NULL);
106 static void action_finalize(const char *const *action)
108 smpi_replay_globals_t globals =
109 (smpi_replay_globals_t) smpi_process_get_user_data();
111 XBT_DEBUG("There are %lu irecvs in the dynar",
112 xbt_dynar_length(globals->irecvs));
113 xbt_dynar_free_container(&(globals->irecvs));
118 static void action_comm_size(const char *const *action)
120 double clock = smpi_process_simulated_elapsed();
122 communicator_size = parse_double(action[2]);
123 log_timed_action (action, clock);
126 static void action_comm_split(const char *const *action)
128 double clock = smpi_process_simulated_elapsed();
130 log_timed_action (action, clock);
133 static void action_comm_dup(const char *const *action)
135 double clock = smpi_process_simulated_elapsed();
137 log_timed_action (action, clock);
140 static void action_compute(const char *const *action)
142 double clock = smpi_process_simulated_elapsed();
143 smpi_execute_flops(parse_double(action[2]));
145 log_timed_action (action, clock);
148 static void action_send(const char *const *action)
150 int to = atoi(action[2]);
151 double size=parse_double(action[3]);
152 double clock = smpi_process_simulated_elapsed();
155 MPI_CURRENT_TYPE=decode_datatype(action[4]);
157 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
161 int rank = smpi_comm_rank(MPI_COMM_WORLD);
162 TRACE_smpi_computing_out(rank);
163 int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to);
164 TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, size*smpi_datatype_size(MPI_CURRENT_TYPE));
165 TRACE_smpi_send(rank, rank, dst_traced, size*smpi_datatype_size(MPI_CURRENT_TYPE));
168 smpi_mpi_send(NULL, size, MPI_CURRENT_TYPE, to , 0, MPI_COMM_WORLD);
170 log_timed_action (action, clock);
173 TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
174 TRACE_smpi_computing_in(rank);
179 static void action_Isend(const char *const *action)
181 int to = atoi(action[2]);
182 double size=parse_double(action[3]);
183 double clock = smpi_process_simulated_elapsed();
186 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
187 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
190 int rank = smpi_comm_rank(MPI_COMM_WORLD);
191 TRACE_smpi_computing_out(rank);
192 int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to);
193 TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, size*smpi_datatype_size(MPI_CURRENT_TYPE));
194 TRACE_smpi_send(rank, rank, dst_traced, size*smpi_datatype_size(MPI_CURRENT_TYPE));
197 request = smpi_mpi_isend(NULL, size, MPI_CURRENT_TYPE, to, 0,MPI_COMM_WORLD);
200 TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
202 TRACE_smpi_computing_in(rank);
205 xbt_dynar_push(reqq[smpi_comm_rank(MPI_COMM_WORLD)],&request);
207 log_timed_action (action, clock);
210 static void action_recv(const char *const *action) {
211 int from = atoi(action[2]);
212 double size=parse_double(action[3]);
213 double clock = smpi_process_simulated_elapsed();
216 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
217 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
220 int rank = smpi_comm_rank(MPI_COMM_WORLD);
221 int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from);
222 TRACE_smpi_computing_out(rank);
224 TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, size*smpi_datatype_size(MPI_CURRENT_TYPE));
227 smpi_mpi_recv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD, &status);
230 TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
231 TRACE_smpi_recv(rank, src_traced, rank);
232 TRACE_smpi_computing_in(rank);
235 log_timed_action (action, clock);
238 static void action_Irecv(const char *const *action)
240 int from = atoi(action[2]);
241 double size=parse_double(action[3]);
242 double clock = smpi_process_simulated_elapsed();
245 smpi_replay_globals_t globals =
246 (smpi_replay_globals_t) smpi_process_get_user_data();
248 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
249 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
252 int rank = smpi_comm_rank(MPI_COMM_WORLD);
253 int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from);
254 TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, size*smpi_datatype_size(MPI_CURRENT_TYPE));
257 request = smpi_mpi_irecv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD);
260 TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
263 xbt_dynar_push(globals->irecvs,&request);
264 xbt_dynar_push(reqq[smpi_comm_rank(MPI_COMM_WORLD)],&request);
266 log_timed_action (action, clock);
269 static void action_wait(const char *const *action){
270 double clock = smpi_process_simulated_elapsed();
273 smpi_replay_globals_t globals =
274 (smpi_replay_globals_t) smpi_process_get_user_data();
276 xbt_assert(xbt_dynar_length(globals->irecvs),
277 "action wait not preceded by any irecv: %s",
278 xbt_str_join_array(action," "));
279 request = xbt_dynar_pop_as(globals->irecvs,MPI_Request);
281 int rank = request && request->comm != MPI_COMM_NULL
282 ? smpi_comm_rank(request->comm)
284 TRACE_smpi_computing_out(rank);
286 MPI_Group group = smpi_comm_group(request->comm);
287 int src_traced = smpi_group_rank(group, request->src);
288 int dst_traced = smpi_group_rank(group, request->dst);
289 int is_wait_for_receive = request->recv;
290 TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__, -1);
292 smpi_mpi_wait(&request, &status);
294 TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
295 if (is_wait_for_receive) {
296 TRACE_smpi_recv(rank, src_traced, dst_traced);
298 TRACE_smpi_computing_in(rank);
301 log_timed_action (action, clock);
304 static void action_waitall(const char *const *action){
305 double clock = smpi_process_simulated_elapsed();
306 int count_requests=0;
309 count_requests=xbt_dynar_length(reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
311 if (count_requests>0) {
312 MPI_Request requests[count_requests];
313 MPI_Status status[count_requests];
315 /* The reqq is an array of dynars. Its index corresponds to the rank.
316 Thus each rank saves its own requests to the array request. */
317 xbt_dynar_foreach(reqq[smpi_comm_rank(MPI_COMM_WORLD)],i,requests[i]);
320 //save information from requests
322 xbt_dynar_t srcs = xbt_dynar_new(sizeof(int), NULL);
323 xbt_dynar_t dsts = xbt_dynar_new(sizeof(int), NULL);
324 xbt_dynar_t recvs = xbt_dynar_new(sizeof(int), NULL);
325 for (i = 0; i < count_requests; i++) {
327 int *asrc = xbt_new(int, 1);
328 int *adst = xbt_new(int, 1);
329 int *arecv = xbt_new(int, 1);
330 *asrc = requests[i]->src;
331 *adst = requests[i]->dst;
332 *arecv = requests[i]->recv;
333 xbt_dynar_insert_at(srcs, i, asrc);
334 xbt_dynar_insert_at(dsts, i, adst);
335 xbt_dynar_insert_at(recvs, i, arecv);
340 int *t = xbt_new(int, 1);
341 xbt_dynar_insert_at(srcs, i, t);
342 xbt_dynar_insert_at(dsts, i, t);
343 xbt_dynar_insert_at(recvs, i, t);
347 int rank_traced = smpi_process_index();
348 TRACE_smpi_computing_out(rank_traced);
350 TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__, count_requests);
353 smpi_mpi_waitall(count_requests, requests, status);
356 for (i = 0; i < count_requests; i++) {
357 int src_traced, dst_traced, is_wait_for_receive;
358 xbt_dynar_get_cpy(srcs, i, &src_traced);
359 xbt_dynar_get_cpy(dsts, i, &dst_traced);
360 xbt_dynar_get_cpy(recvs, i, &is_wait_for_receive);
361 if (is_wait_for_receive) {
362 TRACE_smpi_recv(rank_traced, src_traced, dst_traced);
365 TRACE_smpi_ptp_out(rank_traced, -1, -1, __FUNCTION__);
367 xbt_dynar_free(&srcs);
368 xbt_dynar_free(&dsts);
369 xbt_dynar_free(&recvs);
370 TRACE_smpi_computing_in(rank_traced);
373 xbt_dynar_reset(reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
375 log_timed_action (action, clock);
378 static void action_barrier(const char *const *action){
379 double clock = smpi_process_simulated_elapsed();
381 int rank = smpi_comm_rank(MPI_COMM_WORLD);
382 TRACE_smpi_computing_out(rank);
383 TRACE_smpi_collective_in(rank, -1, __FUNCTION__, smpi_comm_size(MPI_COMM_WORLD));
385 smpi_mpi_barrier(MPI_COMM_WORLD);
387 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
388 TRACE_smpi_computing_in(rank);
391 log_timed_action (action, clock);
395 static void action_bcast(const char *const *action)
397 double size = parse_double(action[2]);
398 double clock = smpi_process_simulated_elapsed();
401 * Initialize MPI_CURRENT_TYPE in order to decrease
402 * the number of the checks
404 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
407 root= atoi(action[3]);
409 MPI_CURRENT_TYPE=decode_datatype(action[4]);
414 int rank = smpi_comm_rank(MPI_COMM_WORLD);
415 TRACE_smpi_computing_out(rank);
416 int root_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), 0);
417 TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__,size*smpi_datatype_size(MPI_CURRENT_TYPE));
420 smpi_mpi_bcast(NULL, size, MPI_CURRENT_TYPE, root, MPI_COMM_WORLD);
422 TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
423 TRACE_smpi_computing_in(rank);
426 log_timed_action (action, clock);
429 static void action_reduce(const char *const *action)
431 double comm_size = parse_double(action[2]);
432 double comp_size = parse_double(action[3]);
433 double clock = smpi_process_simulated_elapsed();
435 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
438 root= atoi(action[4]);
440 MPI_CURRENT_TYPE=decode_datatype(action[5]);
445 int rank = smpi_comm_rank(MPI_COMM_WORLD);
446 TRACE_smpi_computing_out(rank);
447 int root_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), 0);
448 TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__,comm_size*smpi_datatype_size(MPI_CURRENT_TYPE));
450 mpi_coll_reduce_fun(NULL, NULL, comm_size, MPI_CURRENT_TYPE, MPI_OP_NULL, root, MPI_COMM_WORLD);
451 smpi_execute_flops(comp_size);
453 TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
454 TRACE_smpi_computing_in(rank);
457 log_timed_action (action, clock);
460 static void action_allReduce(const char *const *action) {
461 double comm_size = parse_double(action[2]);
462 double comp_size = parse_double(action[3]);
464 if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
465 else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
467 double clock = smpi_process_simulated_elapsed();
469 int rank = smpi_comm_rank(MPI_COMM_WORLD);
470 TRACE_smpi_computing_out(rank);
471 TRACE_smpi_collective_in(rank, -1, __FUNCTION__,comp_size*smpi_datatype_size(MPI_CURRENT_TYPE));
473 mpi_coll_reduce_fun(NULL, NULL, comm_size, MPI_CURRENT_TYPE, MPI_OP_NULL, 0, MPI_COMM_WORLD);
474 smpi_execute_flops(comp_size);
475 mpi_coll_bcast_fun(NULL, comm_size, MPI_CURRENT_TYPE, 0, MPI_COMM_WORLD);
477 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
478 TRACE_smpi_computing_in(rank);
481 log_timed_action (action, clock);
484 static void action_allToAll(const char *const *action) {
485 double clock = smpi_process_simulated_elapsed();
486 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
487 int send_size = parse_double(action[2]);
488 int recv_size = parse_double(action[3]);
489 MPI_Datatype MPI_CURRENT_TYPE2;
492 MPI_CURRENT_TYPE=decode_datatype(action[4]);
493 MPI_CURRENT_TYPE2=decode_datatype(action[5]);
496 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
497 MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
499 void *send = calloc(send_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE));
500 void *recv = calloc(recv_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
503 int rank = smpi_process_index();
504 TRACE_smpi_computing_out(rank);
505 TRACE_smpi_collective_in(rank, -1, __FUNCTION__,send_size*smpi_datatype_size(MPI_CURRENT_TYPE));
508 mpi_coll_alltoall_fun(send, send_size, MPI_CURRENT_TYPE, recv, recv_size, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
511 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
512 TRACE_smpi_computing_in(rank);
515 log_timed_action (action, clock);
521 static void action_gather(const char *const *action) {
523 The structure of the gather action for the rank 0 (total 4 processes)
528 1) 68 is the sendcounts
529 2) 68 is the recvcounts
530 3) 0 is the root node
531 4) 0 is the send datatype id, see decode_datatype()
532 5) 0 is the recv datatype id, see decode_datatype()
534 double clock = smpi_process_simulated_elapsed();
535 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
536 int send_size = parse_double(action[2]);
537 int recv_size = parse_double(action[3]);
538 MPI_Datatype MPI_CURRENT_TYPE2;
540 MPI_CURRENT_TYPE=decode_datatype(action[5]);
541 MPI_CURRENT_TYPE2=decode_datatype(action[6]);
543 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
544 MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
546 void *send = calloc(send_size, smpi_datatype_size(MPI_CURRENT_TYPE));
547 void *recv = calloc(recv_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
549 int root=atoi(action[4]);
550 int rank = smpi_process_index();
553 recv = calloc(recv_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
556 TRACE_smpi_computing_out(rank);
557 TRACE_smpi_collective_in(rank, -1, __FUNCTION__,send_size*smpi_datatype_size(MPI_CURRENT_TYPE));
559 smpi_mpi_gather(send, send_size, MPI_CURRENT_TYPE,
560 recv, recv_size, MPI_CURRENT_TYPE2,
561 root, MPI_COMM_WORLD);
564 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
565 TRACE_smpi_computing_in(rank);
568 log_timed_action (action, clock);
574 static void action_reducescatter(const char *const *action) {
577 The structure of the reducescatter action for the rank 0 (total 4 processes)
579 0 reduceScatter 275427 275427 275427 204020 11346849 0
582 1) The first four values after the name of the action declare the recvcounts array
583 2) The value 11346849 is the amount of instructions
584 3) The last value corresponds to the datatype, see decode_datatype().
586 We analyze a MPI_Reduce_scatter call to one MPI_Reduce and one MPI_Scatterv.
590 double clock = smpi_process_simulated_elapsed();
591 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
592 int comp_size = parse_double(action[2+comm_size]);
593 int *recvcounts = xbt_new0(int, comm_size);
594 int *disps = xbt_new0(int, comm_size);
597 int rank = smpi_process_index();
599 if(action[3+comm_size])
600 MPI_CURRENT_TYPE=decode_datatype(action[3+comm_size]);
602 MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
604 for(i=0;i<comm_size;i++) {
605 recvcounts[i] = atoi(action[i+2]);
606 recv_sum=recv_sum+recvcounts[i];
611 TRACE_smpi_computing_out(rank);
612 TRACE_smpi_collective_in(rank, -1, __FUNCTION__, recv_sum*smpi_datatype_size(MPI_CURRENT_TYPE));
614 mpi_coll_reduce_fun(NULL, NULL, recv_sum, MPI_CURRENT_TYPE, MPI_OP_NULL,
615 root, MPI_COMM_WORLD);
616 smpi_mpi_scatterv(NULL, recvcounts, disps, MPI_CURRENT_TYPE, NULL,
617 recvcounts[rank], MPI_CURRENT_TYPE, 0, MPI_COMM_WORLD);
618 smpi_execute_flops(comp_size);
622 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
623 TRACE_smpi_computing_in(rank);
626 log_timed_action (action, clock);
630 static void action_allgatherv(const char *const *action) {
633 The structure of the allgatherv action for the rank 0 (total 4 processes)
635 0 allGatherV 275427 275427 275427 275427 204020
638 1) 275427 is the sendcount
639 2) The next four elements declare the recvcounts array
640 3) No more values mean that the datatype for sent and receive buffer
641 is the default one, see decode_datatype().
645 double clock = smpi_process_simulated_elapsed();
647 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
649 int sendcount=atoi(action[2]);
650 int *recvcounts = xbt_new0(int, comm_size);
651 int *disps = xbt_new0(int, comm_size);
653 MPI_Datatype MPI_CURRENT_TYPE2;
655 if(action[3+comm_size]) {
656 MPI_CURRENT_TYPE = decode_datatype(action[3+comm_size]);
657 MPI_CURRENT_TYPE2 = decode_datatype(action[4+comm_size]);
659 MPI_CURRENT_TYPE = MPI_DEFAULT_TYPE;
660 MPI_CURRENT_TYPE2 = MPI_DEFAULT_TYPE;
662 void *sendbuf = calloc(sendcount, smpi_datatype_size(MPI_CURRENT_TYPE));
664 for(i=0;i<comm_size;i++) {
665 recvcounts[i] = atoi(action[i+3]);
666 recv_sum=recv_sum+recvcounts[i];
668 void *recvbuf = calloc(recv_sum, smpi_datatype_size(MPI_CURRENT_TYPE2));
671 int rank = MPI_COMM_WORLD != MPI_COMM_NULL ? smpi_process_index() : -1;
672 TRACE_smpi_computing_out(rank);
673 TRACE_smpi_collective_in(rank, -1, __FUNCTION__,sendcount*smpi_datatype_size(MPI_CURRENT_TYPE));
676 mpi_coll_allgatherv_fun(sendbuf, sendcount, MPI_CURRENT_TYPE, recvbuf, recvcounts, disps, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
679 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
680 TRACE_smpi_computing_in(rank);
683 log_timed_action (action, clock);
686 xbt_free(recvcounts);
691 static void action_allToAllv(const char *const *action) {
693 The structure of the allToAllV action for the rank 0 (total 4 processes)
695 0 allToAllV 100 1 7 10 12 100 1 70 10 5
698 1) 100 is the size of the send buffer *sizeof(int),
699 2) 1 7 10 12 is the sendcounts array
700 3) 100*sizeof(int) is the size of the receiver buffer
701 4) 1 70 10 5 is the recvcounts array
706 double clock = smpi_process_simulated_elapsed();
708 int comm_size = smpi_comm_size(MPI_COMM_WORLD);
709 int send_buf_size=0,recv_buf_size=0,i=0;
710 int *sendcounts = xbt_new0(int, comm_size);
711 int *recvcounts = xbt_new0(int, comm_size);
712 int *senddisps = xbt_new0(int, comm_size);
713 int *recvdisps = xbt_new0(int, comm_size);
715 MPI_Datatype MPI_CURRENT_TYPE2;
717 send_buf_size=parse_double(action[2]);
718 recv_buf_size=parse_double(action[3+comm_size]);
719 if(action[4+2*comm_size]) {
720 MPI_CURRENT_TYPE=decode_datatype(action[4+2*comm_size]);
721 MPI_CURRENT_TYPE2=decode_datatype(action[5+2*comm_size]);
724 MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
725 MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
728 void *sendbuf = calloc(send_buf_size, smpi_datatype_size(MPI_CURRENT_TYPE));
729 void *recvbuf = calloc(recv_buf_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
731 for(i=0;i<comm_size;i++) {
732 sendcounts[i] = atoi(action[i+3]);
733 recvcounts[i] = atoi(action[i+4+comm_size]);
738 int rank = MPI_COMM_WORLD != MPI_COMM_NULL ? smpi_process_index() : -1;
739 TRACE_smpi_computing_out(rank);
741 for(i=0;i<comm_size;i++) count+=sendcounts[i];
742 TRACE_smpi_collective_in(rank, -1, __FUNCTION__,count*smpi_datatype_size(MPI_CURRENT_TYPE));
744 mpi_coll_alltoallv_fun(sendbuf, sendcounts, senddisps, MPI_CURRENT_TYPE,
745 recvbuf, recvcounts, recvdisps, MPI_CURRENT_TYPE,
748 TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
749 TRACE_smpi_computing_in(rank);
752 log_timed_action (action, clock);
755 xbt_free(sendcounts);
756 xbt_free(recvcounts);
761 void smpi_replay_init(int *argc, char***argv){
762 PMPI_Init(argc, argv);
763 if (!smpi_process_index()){
764 _xbt_replay_action_init();
765 xbt_replay_action_register("init", action_init);
766 xbt_replay_action_register("finalize", action_finalize);
767 xbt_replay_action_register("comm_size", action_comm_size);
768 xbt_replay_action_register("comm_split", action_comm_split);
769 xbt_replay_action_register("comm_dup", action_comm_dup);
770 xbt_replay_action_register("send", action_send);
771 xbt_replay_action_register("Isend", action_Isend);
772 xbt_replay_action_register("recv", action_recv);
773 xbt_replay_action_register("Irecv", action_Irecv);
774 xbt_replay_action_register("wait", action_wait);
775 xbt_replay_action_register("waitAll", action_waitall);
776 xbt_replay_action_register("barrier", action_barrier);
777 xbt_replay_action_register("bcast", action_bcast);
778 xbt_replay_action_register("reduce", action_reduce);
779 xbt_replay_action_register("allReduce", action_allReduce);
780 xbt_replay_action_register("allToAll", action_allToAll);
781 xbt_replay_action_register("allToAllV", action_allToAllv);
782 xbt_replay_action_register("gather", action_gather);
783 xbt_replay_action_register("allGatherV", action_allgatherv);
784 xbt_replay_action_register("reduceScatter", action_reducescatter);
785 xbt_replay_action_register("compute", action_compute);
788 xbt_replay_action_runner(*argc, *argv);
791 int smpi_replay_finalize(){
793 /* One active process will stop. Decrease the counter*/
795 XBT_DEBUG("There are %lu elements in reqq[*]",
796 xbt_dynar_length(reqq[smpi_comm_rank(MPI_COMM_WORLD)]));
797 xbt_dynar_free(&reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
798 if(!active_processes){
799 /* Last process alive speaking */
800 /* end the simulated timer */
801 sim_time = smpi_process_simulated_elapsed();
802 XBT_INFO("Simulation time %g", sim_time);
803 _xbt_replay_action_exit();
807 smpi_mpi_barrier(MPI_COMM_WORLD);
808 return PMPI_Finalize();