Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
avoid double variable definition when tracing is activated (+some
[simgrid.git] / src / smpi / smpi_replay.c
1 /* Copyright (c) 2009, 2010, 2011, 2012. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7
8 #include "private.h"
9 #include <stdio.h>
10 #include <xbt.h>
11 #include <xbt/replay.h>
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_replay,smpi,"Trace Replay with SMPI");
14
15 int communicator_size = 0;
16 static int active_processes = 0;
17 xbt_dynar_t *reqq = NULL;
18
19 MPI_Datatype MPI_DEFAULT_TYPE;
20 MPI_Datatype MPI_CURRENT_TYPE;
21
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);
26     free(name);
27   }
28 }
29
30 typedef struct {
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;
34
35
36 /* Helper function */
37 static double parse_double(const char *string)
38 {
39   double value;
40   char *endptr;
41   value = strtod(string, &endptr);
42   if (*endptr != '\0')
43     THROWF(unknown_error, 0, "%s is not a double", string);
44   return value;
45 }
46
47 static MPI_Datatype decode_datatype(const char *const action)
48 {
49 // Declared datatypes,
50  
51   switch(atoi(action))
52   {
53     case 0:
54       MPI_CURRENT_TYPE=MPI_DOUBLE;
55       break;
56     case 1:
57       MPI_CURRENT_TYPE=MPI_INT;
58       break;
59     case 2:
60       MPI_CURRENT_TYPE=MPI_CHAR;
61       break;
62     case 3:
63       MPI_CURRENT_TYPE=MPI_SHORT;
64       break;
65     case 4:
66       MPI_CURRENT_TYPE=MPI_LONG;
67       break;
68     case 5:
69       MPI_CURRENT_TYPE=MPI_FLOAT;
70       break;
71     case 6:
72       MPI_CURRENT_TYPE=MPI_BYTE;
73       break;
74     default:
75       MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
76   
77   }
78    return MPI_CURRENT_TYPE;
79 }
80
81 static void action_init(const char *const *action)
82 {
83   int i;
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);
88
89   if(action[2]) MPI_DEFAULT_TYPE= MPI_DOUBLE; // default MPE dataype 
90   else MPI_DEFAULT_TYPE= MPI_BYTE; // default TAU datatype
91   
92   smpi_process_set_user_data((void*) globals);
93
94   /* start a simulated timer */
95   smpi_process_simulated_start();
96   /*initialize the number of active processes */
97   active_processes = smpi_process_count();
98
99   if (!reqq) {
100     reqq=xbt_new0(xbt_dynar_t,active_processes);
101   
102     for(i=0;i<active_processes;i++){
103       reqq[i]=xbt_dynar_new(sizeof(MPI_Request),NULL);
104     }
105   }
106 }
107
108 static void action_finalize(const char *const *action)
109 {
110   smpi_replay_globals_t globals =
111       (smpi_replay_globals_t) smpi_process_get_user_data();
112   if (globals){
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));
117   }
118   free(globals);
119 }
120
121 static void action_comm_size(const char *const *action)
122 {
123   double clock = smpi_process_simulated_elapsed();
124
125   communicator_size = parse_double(action[2]);
126   log_timed_action (action, clock);
127 }
128
129 static void action_comm_split(const char *const *action)
130 {
131   double clock = smpi_process_simulated_elapsed();
132
133   log_timed_action (action, clock);
134 }
135
136 static void action_comm_dup(const char *const *action)
137 {
138   double clock = smpi_process_simulated_elapsed();
139
140   log_timed_action (action, clock);
141 }
142
143 static void action_compute(const char *const *action)
144 {
145   double clock = smpi_process_simulated_elapsed();
146   smpi_execute_flops(parse_double(action[2]));
147
148   log_timed_action (action, clock);
149 }
150
151 static void action_send(const char *const *action)
152 {
153   int to = atoi(action[2]);
154   double size=parse_double(action[3]);
155   double clock = smpi_process_simulated_elapsed();
156
157   if(action[4]) {
158     MPI_CURRENT_TYPE=decode_datatype(action[4]);
159   } else {
160     MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
161   }
162     
163 #ifdef HAVE_TRACING
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);
169 #endif
170
171   smpi_mpi_send(NULL, size, MPI_CURRENT_TYPE, to , 0, MPI_COMM_WORLD);
172
173   log_timed_action (action, clock);
174
175   #ifdef HAVE_TRACING
176   TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
177   TRACE_smpi_computing_in(rank);
178 #endif
179
180 }
181
182 static void action_Isend(const char *const *action)
183 {
184   int to = atoi(action[2]);
185   double size=parse_double(action[3]);
186   double clock = smpi_process_simulated_elapsed();
187   MPI_Request request;
188
189   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
190   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
191
192   smpi_replay_globals_t globals =
193      (smpi_replay_globals_t) smpi_process_get_user_data();
194 #ifdef HAVE_TRACING
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);
200 #endif
201
202   request = smpi_mpi_isend(NULL, size, MPI_CURRENT_TYPE, to, 0,MPI_COMM_WORLD);
203   
204 #ifdef HAVE_TRACING
205   TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
206   request->send = 1;
207   TRACE_smpi_computing_in(rank);
208 #endif
209
210   xbt_dynar_push(globals->isends,&request);
211   xbt_dynar_push(reqq[smpi_comm_rank(MPI_COMM_WORLD)],&request);
212
213   log_timed_action (action, clock);
214 }
215
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();
220   MPI_Status status;
221
222   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
223   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
224   
225 #ifdef HAVE_TRACING
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);
229
230   TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__);
231 #endif
232
233   smpi_mpi_recv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD, &status);
234
235 #ifdef HAVE_TRACING
236   TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
237   TRACE_smpi_recv(rank, src_traced, rank);
238   TRACE_smpi_computing_in(rank);
239 #endif
240
241   log_timed_action (action, clock);
242 }
243
244 static void action_Irecv(const char *const *action)
245 {
246   int from = atoi(action[2]);
247   double size=parse_double(action[3]);
248   double clock = smpi_process_simulated_elapsed();
249   MPI_Request request;
250
251   smpi_replay_globals_t globals =
252      (smpi_replay_globals_t) smpi_process_get_user_data();
253   
254   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
255   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
256
257 #ifdef HAVE_TRACING
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__);
261 #endif
262
263   request = smpi_mpi_irecv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD);
264   
265 #ifdef HAVE_TRACING
266   TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
267   request->recv = 1;
268 #endif
269   xbt_dynar_push(globals->irecvs,&request);
270   xbt_dynar_push(reqq[smpi_comm_rank(MPI_COMM_WORLD)],&request);
271
272   log_timed_action (action, clock);
273 }
274
275 static void action_wait(const char *const *action){
276   double clock = smpi_process_simulated_elapsed();
277   MPI_Request request;
278   MPI_Status status;
279   smpi_replay_globals_t globals =
280       (smpi_replay_globals_t) smpi_process_get_user_data();
281
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);
286 #ifdef HAVE_TRACING
287   int rank = request && request->comm != MPI_COMM_NULL
288       ? smpi_comm_rank(request->comm)
289       : -1;
290   TRACE_smpi_computing_out(rank);
291
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__);
297 #endif
298   smpi_mpi_wait(&request, &status);
299 #ifdef HAVE_TRACING
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);
303   }
304   TRACE_smpi_computing_in(rank);
305 #endif
306
307   log_timed_action (action, clock);
308 }
309
310 static void action_waitall(const char *const *action){
311   double clock = smpi_process_simulated_elapsed();
312   int count_requests=0;
313   unsigned int i=0;
314
315   count_requests=xbt_dynar_length(reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
316
317   if (count_requests>0) {
318     MPI_Request requests[count_requests];
319     MPI_Status status[count_requests];
320   
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]); 
324     
325   #ifdef HAVE_TRACING
326    //save information from requests
327  
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++) {
332     if(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);
342       xbt_free(asrc);
343       xbt_free(adst);
344       xbt_free(arecv);
345     }else {
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);
350       xbt_free(t);
351     }
352    }
353    int rank_traced = smpi_process_index();
354    TRACE_smpi_computing_out(rank_traced);
355
356    TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__);
357   #endif
358
359     smpi_mpi_waitall(count_requests, requests, status);
360
361   #ifdef HAVE_TRACING
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);
369     }
370    }
371    TRACE_smpi_ptp_out(rank_traced, -1, -1, __FUNCTION__);
372    //clean-up of dynars
373    xbt_dynar_free(&srcs);
374    xbt_dynar_free(&dsts);
375    xbt_dynar_free(&recvs);
376    TRACE_smpi_computing_in(rank_traced);
377   #endif
378    
379    xbt_dynar_reset(reqq[smpi_comm_rank(MPI_COMM_WORLD)]);
380   }
381   log_timed_action (action, clock);
382 }
383
384 static void action_barrier(const char *const *action){
385   double clock = smpi_process_simulated_elapsed();
386 #ifdef HAVE_TRACING
387   int rank = smpi_comm_rank(MPI_COMM_WORLD);
388   TRACE_smpi_computing_out(rank);
389   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
390 #endif
391   smpi_mpi_barrier(MPI_COMM_WORLD);
392 #ifdef HAVE_TRACING
393   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
394   TRACE_smpi_computing_in(rank);
395 #endif
396
397   log_timed_action (action, clock);
398 }
399
400
401 static void action_bcast(const char *const *action)
402 {
403   double size = parse_double(action[2]);
404   double clock = smpi_process_simulated_elapsed();
405   int root=0;
406   /*
407    * Initialize MPI_CURRENT_TYPE in order to decrease
408    * the number of the checks
409    * */
410   MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;  
411
412   if(action[3]) {
413     root= atoi(action[3]);
414     if(action[4]) {
415       MPI_CURRENT_TYPE=decode_datatype(action[4]);   
416     }
417   }
418   
419 #ifdef HAVE_TRACING
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__);
424 #endif
425
426   smpi_mpi_bcast(NULL, size, MPI_CURRENT_TYPE, root, MPI_COMM_WORLD);
427 #ifdef HAVE_TRACING
428   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
429   TRACE_smpi_computing_in(rank);
430 #endif
431
432   log_timed_action (action, clock);
433 }
434
435 static void action_reduce(const char *const *action)
436 {
437   double comm_size = parse_double(action[2]);
438   double comp_size = parse_double(action[3]);
439   double clock = smpi_process_simulated_elapsed();
440   int root=0;
441   MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
442   
443   if(action[4]) {
444       root= atoi(action[4]);
445       if(action[5]) {
446         MPI_CURRENT_TYPE=decode_datatype(action[5]);
447       }
448   }
449
450 #ifdef HAVE_TRACING
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__);
455 #endif
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);
458 #ifdef HAVE_TRACING
459   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
460   TRACE_smpi_computing_in(rank);
461 #endif
462
463   log_timed_action (action, clock);
464 }
465
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]);
469   
470   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
471   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
472   
473   double clock = smpi_process_simulated_elapsed();
474 #ifdef HAVE_TRACING
475   int rank = smpi_comm_rank(MPI_COMM_WORLD);
476   TRACE_smpi_computing_out(rank);
477   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
478 #endif
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);
482 #ifdef HAVE_TRACING
483   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
484   TRACE_smpi_computing_in(rank);
485 #endif
486
487   log_timed_action (action, clock);
488 }
489
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;
496   
497   if(action[4]) {
498     MPI_CURRENT_TYPE=decode_datatype(action[4]);
499     MPI_CURRENT_TYPE2=decode_datatype(action[5]);
500   }
501   else {
502     MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
503     MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
504   }
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));  
507
508 #ifdef HAVE_TRACING
509   int rank = smpi_process_index();
510   TRACE_smpi_computing_out(rank);
511   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
512 #endif
513   
514   mpi_coll_alltoall_fun(send, send_size, MPI_CURRENT_TYPE, recv, recv_size, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
515
516 #ifdef HAVE_TRACING
517   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
518   TRACE_smpi_computing_in(rank);
519 #endif
520
521   log_timed_action (action, clock);
522   xbt_free(send);
523   xbt_free(recv);
524 }
525
526
527 static void action_gather(const char *const *action) {
528   
529   
530   /*
531  The structure of the gather action for the rank 0 (total 4 processes) 
532  is the following:   
533  0 gather 68 68 0 0 0
534
535   where: 
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()
541     
542   */
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;
548   if(action[5]) {
549     MPI_CURRENT_TYPE=decode_datatype(action[5]);
550     MPI_CURRENT_TYPE2=decode_datatype(action[6]);
551   } else {
552     MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
553     MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
554   }
555   void *send = calloc(send_size, smpi_datatype_size(MPI_CURRENT_TYPE));  
556   void *recv = calloc(recv_size, smpi_datatype_size(MPI_CURRENT_TYPE2));  
557
558   int root=atoi(action[4]);
559   int rank = smpi_process_index();
560
561   if(rank==root)
562     recv = calloc(recv_size*comm_size, smpi_datatype_size(MPI_CURRENT_TYPE2));
563
564 #ifdef HAVE_TRACING
565   TRACE_smpi_computing_out(rank);
566   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
567 #endif
568 smpi_mpi_gather(send, send_size, MPI_CURRENT_TYPE,
569                 recv, recv_size, MPI_CURRENT_TYPE2,
570                 root, MPI_COMM_WORLD);
571
572 #ifdef HAVE_TRACING
573   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
574   TRACE_smpi_computing_in(rank);
575 #endif
576
577   log_timed_action (action, clock);
578   xbt_free(send);
579   xbt_free(recv);
580 }
581
582
583 static void action_reducescatter(const char *const *action) {
584   
585     /*
586  The structure of the reducescatter action for the rank 0 (total 4 processes) 
587  is the following:   
588 0 reduceScatter 275427 275427 275427 204020 11346849 0
589
590   where: 
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().
594   
595   We analyze a MPI_Reduce_scatter call to one MPI_Reduce and one MPI_Scatterv.
596   
597    */
598
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);  
604   int i=0,recv_sum=0;
605   int root=0;
606   int rank = smpi_process_index();
607
608   if(action[3+comm_size])
609     MPI_CURRENT_TYPE=decode_datatype(action[3+comm_size]);
610   else
611     MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
612
613   for(i=0;i<comm_size;i++) {
614     recvcounts[i] = atoi(action[i+2]);
615     recv_sum=recv_sum+recvcounts[i];
616     disps[i] = 0;
617   }
618
619 #ifdef HAVE_TRACING
620   TRACE_smpi_computing_out(rank);
621   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
622 #endif
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);
628     
629     
630 #ifdef HAVE_TRACING
631   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
632   TRACE_smpi_computing_in(rank);
633 #endif
634
635   log_timed_action (action, clock);
636 }
637
638
639 static void action_allgatherv(const char *const *action) {
640   
641   /*
642  The structure of the allgatherv action for the rank 0 (total 4 processes) 
643  is the following:   
644 0 allGatherV 275427 275427 275427 275427 204020 0 275427 550854 826281 
645
646   where: 
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().
652
653    */
654
655   double clock = smpi_process_simulated_elapsed();
656   
657   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
658   int i=0;
659   int sendcount=atoi(action[2]);
660   int *recvcounts = xbt_new0(int, comm_size);  
661   int *disps = xbt_new0(int, comm_size);  
662   int recv_sum=0;  
663   MPI_Datatype MPI_CURRENT_TYPE2;
664
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]);
668   } else {
669     MPI_CURRENT_TYPE = MPI_DEFAULT_TYPE;
670     MPI_CURRENT_TYPE2 = MPI_DEFAULT_TYPE;    
671   }
672   void *sendbuf = calloc(sendcount, smpi_datatype_size(MPI_CURRENT_TYPE));    
673
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]);
678   }
679   void *recvbuf = calloc(recv_sum, smpi_datatype_size(MPI_CURRENT_TYPE2));  
680
681 #ifdef HAVE_TRACING
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__);
685 #endif
686   
687 mpi_coll_allgatherv_fun(sendbuf, sendcount, MPI_CURRENT_TYPE, recvbuf, recvcounts, disps, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
688
689 #ifdef HAVE_TRACING
690   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
691   TRACE_smpi_computing_in(rank);
692 #endif
693    
694   log_timed_action (action, clock);
695   xbt_free(sendbuf);
696   xbt_free(recvbuf);
697   xbt_free(recvcounts);
698   xbt_free(disps);
699 }
700
701
702 static void action_allToAllv(const char *const *action) {
703   /*
704  The structure of the allToAllV action for the rank 0 (total 4 processes) 
705  is the following:   
706   0 allToAllV 100 1 7 10 12 5 10 20 45 100 1 70 10 5 1 5 77 90
707
708   where: 
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
715     
716    */
717   
718   
719   double clock = smpi_process_simulated_elapsed();
720   
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);  
727
728   MPI_Datatype MPI_CURRENT_TYPE2;
729   
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]);    
735   }
736   else {
737       MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
738       MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
739   }
740   
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));  
743
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]);
749   }
750   
751
752 #ifdef HAVE_TRACING
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__);
756 #endif
757     mpi_coll_alltoallv_fun(sendbuf, sendcounts, senddisps,      MPI_CURRENT_TYPE,
758                                recvbuf, recvcounts, recvdisps, MPI_CURRENT_TYPE,
759                                MPI_COMM_WORLD);
760 #ifdef HAVE_TRACING
761   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
762   TRACE_smpi_computing_in(rank);
763 #endif
764    
765   log_timed_action (action, clock);
766   xbt_free(sendbuf);
767   xbt_free(recvbuf);
768   xbt_free(sendcounts);
769   xbt_free(recvcounts);
770   xbt_free(senddisps);
771   xbt_free(recvdisps);
772
773   
774 }
775
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);
801   }
802
803   xbt_replay_action_runner(*argc, *argv);
804 }
805
806 int smpi_replay_finalize(){
807   double sim_time= 1.;
808   /* One active process will stop. Decrease the counter*/
809   active_processes--;
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();
819     xbt_free(reqq);
820     reqq = NULL;
821   }
822   smpi_mpi_barrier(MPI_COMM_WORLD);
823   return PMPI_Finalize();
824 }