Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add preliminary support for MPI_Pack, MPI_Pack_size, and MPI_Unpack.
[simgrid.git] / src / smpi / smpi_replay.c
1 /* Copyright (c) 2009-2014. 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 #include "private.h"
8 #include <stdio.h>
9 #include <xbt.h>
10 #include <xbt/replay.h>
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_replay,smpi,"Trace Replay with SMPI");
13
14 int communicator_size = 0;
15 static int active_processes = 0;
16 xbt_dynar_t *reqq = NULL;
17
18 MPI_Datatype MPI_DEFAULT_TYPE;
19 MPI_Datatype MPI_CURRENT_TYPE;
20
21 static int sendbuffer_size=0;
22 char* sendbuffer=NULL;
23 static int recvbuffer_size=0;
24 char* recvbuffer=NULL;
25
26 static void log_timed_action (const char *const *action, double clock){
27   if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){
28     char *name = xbt_str_join_array(action, " ");
29     XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock);
30     free(name);
31   }
32 }
33
34 //allocate a single buffer for all sends, growing it if needed
35 void* smpi_get_tmp_sendbuffer(int size){
36   if (!smpi_process_get_replaying())
37         return xbt_malloc(size);
38   if (sendbuffer_size<size){
39     sendbuffer=xbt_realloc(sendbuffer,size);
40     sendbuffer_size=size;
41   }
42   return sendbuffer;
43 }
44 //allocate a single buffer for all recv
45 void* smpi_get_tmp_recvbuffer(int size){
46   if (!smpi_process_get_replaying())
47         return xbt_malloc(size);
48   if (recvbuffer_size<size){
49     recvbuffer=xbt_realloc(recvbuffer,size);
50     recvbuffer_size=size;
51   }
52   return sendbuffer;
53 }
54
55 void smpi_free_tmp_buffer(void* buf){
56   if (!smpi_process_get_replaying())
57     xbt_free(buf);
58 }
59
60 /* Helper function */
61 static double parse_double(const char *string)
62 {
63   double value;
64   char *endptr;
65   value = strtod(string, &endptr);
66   if (*endptr != '\0')
67     THROWF(unknown_error, 0, "%s is not a double", string);
68   return value;
69 }
70
71 static MPI_Datatype decode_datatype(const char *const action)
72 {
73 // Declared datatypes,
74
75   switch(atoi(action))
76   {
77     case 0:
78       MPI_CURRENT_TYPE=MPI_DOUBLE;
79       break;
80     case 1:
81       MPI_CURRENT_TYPE=MPI_INT;
82       break;
83     case 2:
84       MPI_CURRENT_TYPE=MPI_CHAR;
85       break;
86     case 3:
87       MPI_CURRENT_TYPE=MPI_SHORT;
88       break;
89     case 4:
90       MPI_CURRENT_TYPE=MPI_LONG;
91       break;
92     case 5:
93       MPI_CURRENT_TYPE=MPI_FLOAT;
94       break;
95     case 6:
96       MPI_CURRENT_TYPE=MPI_BYTE;
97       break;
98     default:
99       MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
100
101   }
102    return MPI_CURRENT_TYPE;
103 }
104
105
106 const char* encode_datatype(MPI_Datatype datatype)
107 {
108
109   //default type for output is set to MPI_BYTE
110   // MPI_DEFAULT_TYPE is not set for output, use directly MPI_BYTE
111   if (datatype==MPI_BYTE){
112       return "";
113   }
114   if(datatype==MPI_DOUBLE)
115       return "0";
116   if(datatype==MPI_INT)
117       return "1";
118   if(datatype==MPI_CHAR)
119       return "2";
120   if(datatype==MPI_SHORT)
121       return "3";
122   if(datatype==MPI_LONG)
123     return "4";
124   if(datatype==MPI_FLOAT)
125       return "5";
126
127   // default - not implemented.
128   // do not warn here as we pass in this function even for other trace formats
129   return "-1";
130 }
131
132 #define CHECK_ACTION_PARAMS(action, mandatory, optional) {\
133     int i=0;\
134     while(action[i]!=NULL)\
135      i++;\
136     if(i<mandatory+2)                                           \
137     THROWF(arg_error, 0, "%s replay failed.\n" \
138           "%d items were given on the line. First two should be process_id and action.  " \
139           "This action needs after them %d mandatory arguments, and accepts %d optional ones. \n" \
140           "Please contact the Simgrid team if support is needed", __FUNCTION__, i, mandatory, optional);\
141   }
142
143
144 static void action_init(const char *const *action)
145 {
146   int i;
147   XBT_DEBUG("Initialize the counters");
148   CHECK_ACTION_PARAMS(action, 0, 1);
149   if(action[2]) MPI_DEFAULT_TYPE= MPI_DOUBLE; // default MPE dataype 
150   else MPI_DEFAULT_TYPE= MPI_BYTE; // default TAU datatype
151
152   /* start a simulated timer */
153   smpi_process_simulated_start();
154   /*initialize the number of active processes */
155   active_processes = smpi_process_count();
156
157   if (!reqq) {
158     reqq=xbt_new0(xbt_dynar_t,active_processes);
159
160     for(i=0;i<active_processes;i++){
161       reqq[i]=xbt_dynar_new(sizeof(MPI_Request),&xbt_free_ref);
162     }
163   }
164 }
165
166 static void action_finalize(const char *const *action)
167 {
168 }
169
170 static void action_comm_size(const char *const *action)
171 {
172   double clock = smpi_process_simulated_elapsed();
173
174   communicator_size = parse_double(action[2]);
175   log_timed_action (action, clock);
176 }
177
178 static void action_comm_split(const char *const *action)
179 {
180   double clock = smpi_process_simulated_elapsed();
181
182   log_timed_action (action, clock);
183 }
184
185 static void action_comm_dup(const char *const *action)
186 {
187   double clock = smpi_process_simulated_elapsed();
188
189   log_timed_action (action, clock);
190 }
191
192 static void action_compute(const char *const *action)
193 {
194   CHECK_ACTION_PARAMS(action, 1, 0);
195   double clock = smpi_process_simulated_elapsed();
196   double flops= parse_double(action[2]);
197 #ifdef HAVE_TRACING
198   int rank = smpi_process_index();
199   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
200   extra->type=TRACING_COMPUTING;
201   extra->comp_size=flops;
202   TRACE_smpi_computing_in(rank, extra);
203 #endif
204   smpi_execute_flops(flops);
205 #ifdef HAVE_TRACING
206   TRACE_smpi_computing_out(rank);
207 #endif
208
209   log_timed_action (action, clock);
210 }
211
212 static void action_send(const char *const *action)
213 {
214   CHECK_ACTION_PARAMS(action, 2, 1);
215   int to = atoi(action[2]);
216   double size=parse_double(action[3]);
217   double clock = smpi_process_simulated_elapsed();
218
219   if(action[4]) {
220     MPI_CURRENT_TYPE=decode_datatype(action[4]);
221   } else {
222     MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
223   }
224
225 #ifdef HAVE_TRACING
226   int rank = smpi_process_index();
227
228   int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to);
229   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
230   extra->type = TRACING_SEND;
231   extra->send_size = size;
232   extra->src = rank;
233   extra->dst = dst_traced;
234   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
235   TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, extra);
236   TRACE_smpi_send(rank, rank, dst_traced, size*smpi_datatype_size(MPI_CURRENT_TYPE));
237 #endif
238
239   smpi_mpi_send(NULL, size, MPI_CURRENT_TYPE, to , 0, MPI_COMM_WORLD);
240
241   log_timed_action (action, clock);
242
243   #ifdef HAVE_TRACING
244   TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
245 #endif
246
247 }
248
249 static void action_Isend(const char *const *action)
250 {
251   CHECK_ACTION_PARAMS(action, 2, 1);
252   int to = atoi(action[2]);
253   double size=parse_double(action[3]);
254   double clock = smpi_process_simulated_elapsed();
255   MPI_Request request;
256
257   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
258   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
259
260 #ifdef HAVE_TRACING
261   int rank = smpi_process_index();
262   int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to);
263   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
264   extra->type = TRACING_ISEND;
265   extra->send_size = size;
266   extra->src = rank;
267   extra->dst = dst_traced;
268   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
269   TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, extra);
270   TRACE_smpi_send(rank, rank, dst_traced, size*smpi_datatype_size(MPI_CURRENT_TYPE));
271 #endif
272
273   request = smpi_mpi_isend(NULL, size, MPI_CURRENT_TYPE, to, 0,MPI_COMM_WORLD);
274
275 #ifdef HAVE_TRACING
276   TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
277   request->send = 1;
278 #endif
279
280   xbt_dynar_push(reqq[smpi_process_index()],&request);
281
282   log_timed_action (action, clock);
283 }
284
285 static void action_recv(const char *const *action) {
286   CHECK_ACTION_PARAMS(action, 2, 1);
287   int from = atoi(action[2]);
288   double size=parse_double(action[3]);
289   double clock = smpi_process_simulated_elapsed();
290   MPI_Status status;
291
292   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
293   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
294
295 #ifdef HAVE_TRACING
296   int rank = smpi_process_index();
297   int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from);
298
299   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
300   extra->type = TRACING_RECV;
301   extra->send_size = size;
302   extra->src = src_traced;
303   extra->dst = rank;
304   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
305   TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, extra);
306 #endif
307
308   //unknow size from the receiver pov
309   if(size==-1){
310       smpi_mpi_probe(from, 0, MPI_COMM_WORLD, &status);
311       size=status.count;
312   }
313
314   smpi_mpi_recv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD, &status);
315
316 #ifdef HAVE_TRACING
317   TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
318   TRACE_smpi_recv(rank, src_traced, rank);
319 #endif
320
321   log_timed_action (action, clock);
322 }
323
324 static void action_Irecv(const char *const *action)
325 {
326   CHECK_ACTION_PARAMS(action, 2, 1);
327   int from = atoi(action[2]);
328   double size=parse_double(action[3]);
329   double clock = smpi_process_simulated_elapsed();
330   MPI_Request request;
331
332   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
333   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
334
335 #ifdef HAVE_TRACING
336   int rank = smpi_process_index();
337   int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from);
338   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
339   extra->type = TRACING_IRECV;
340   extra->send_size = size;
341   extra->src = src_traced;
342   extra->dst = rank;
343   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
344   TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, extra);
345 #endif
346   MPI_Status status;
347   //unknow size from the receiver pov
348   if(size==-1){
349       smpi_mpi_probe(from, 0, MPI_COMM_WORLD, &status);
350       size=status.count;
351   }
352
353   request = smpi_mpi_irecv(NULL, size, MPI_CURRENT_TYPE, from, 0, MPI_COMM_WORLD);
354
355 #ifdef HAVE_TRACING
356   TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
357   request->recv = 1;
358 #endif
359   xbt_dynar_push(reqq[smpi_process_index()],&request);
360
361   log_timed_action (action, clock);
362 }
363
364 static void action_test(const char *const *action){
365   CHECK_ACTION_PARAMS(action, 0, 0);
366   double clock = smpi_process_simulated_elapsed();
367   MPI_Request request;
368   MPI_Status status;
369   int flag = TRUE;
370
371   request = xbt_dynar_pop_as(reqq[smpi_process_index()],MPI_Request);
372   //if request is null here, this may mean that a previous test has succeeded 
373   //Different times in traced application and replayed version may lead to this 
374   //In this case, ignore the extra calls.
375   if(request){
376 #ifdef HAVE_TRACING
377   int rank = smpi_process_index();
378   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
379   extra->type=TRACING_TEST;
380   TRACE_smpi_testing_in(rank, extra);
381 #endif
382
383     flag = smpi_mpi_test(&request, &status);
384
385   XBT_DEBUG("MPI_Test result: %d", flag);
386   /* push back request in dynar to be caught by a subsequent wait. if the test
387    * did succeed, the request is now NULL.
388    */
389   xbt_dynar_push_as(reqq[smpi_process_index()],MPI_Request, request);
390
391 #ifdef HAVE_TRACING
392   TRACE_smpi_testing_out(rank);
393 #endif
394   }
395   log_timed_action (action, clock);
396 }
397
398 static void action_wait(const char *const *action){
399   CHECK_ACTION_PARAMS(action, 0, 0);
400   double clock = smpi_process_simulated_elapsed();
401   MPI_Request request;
402   MPI_Status status;
403
404   xbt_assert(xbt_dynar_length(reqq[smpi_process_index()]),
405       "action wait not preceded by any irecv or isend: %s",
406       xbt_str_join_array(action," "));
407   request = xbt_dynar_pop_as(reqq[smpi_process_index()],MPI_Request);
408
409   if (!request){
410     /* Assuming that the trace is well formed, this mean the comm might have
411      * been caught by a MPI_test. Then just return.
412      */
413     return;
414   }
415
416 #ifdef HAVE_TRACING
417   int rank = request->comm != MPI_COMM_NULL
418       ? smpi_comm_rank(request->comm)
419       : -1;
420
421   MPI_Group group = smpi_comm_group(request->comm);
422   int src_traced = smpi_group_rank(group, request->src);
423   int dst_traced = smpi_group_rank(group, request->dst);
424   int is_wait_for_receive = request->recv;
425   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
426   extra->type = TRACING_WAIT;
427   TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__, extra);
428 #endif
429   smpi_mpi_wait(&request, &status);
430 #ifdef HAVE_TRACING
431   TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
432   if (is_wait_for_receive) {
433     TRACE_smpi_recv(rank, src_traced, dst_traced);
434   }
435 #endif
436
437   log_timed_action (action, clock);
438 }
439
440 static void action_waitall(const char *const *action){
441   CHECK_ACTION_PARAMS(action, 0, 0);
442   double clock = smpi_process_simulated_elapsed();
443   int count_requests=0;
444   unsigned int i=0;
445
446   count_requests=xbt_dynar_length(reqq[smpi_process_index()]);
447
448   if (count_requests>0) {
449     MPI_Request requests[count_requests];
450     MPI_Status status[count_requests];
451
452     /*  The reqq is an array of dynars. Its index corresponds to the rank.
453      Thus each rank saves its own requests to the array request. */
454     xbt_dynar_foreach(reqq[smpi_process_index()],i,requests[i]); 
455
456   #ifdef HAVE_TRACING
457    //save information from requests
458
459    xbt_dynar_t srcs = xbt_dynar_new(sizeof(int), NULL);
460    xbt_dynar_t dsts = xbt_dynar_new(sizeof(int), NULL);
461    xbt_dynar_t recvs = xbt_dynar_new(sizeof(int), NULL);
462    for (i = 0; i < count_requests; i++) {
463     if(requests[i]){
464       int *asrc = xbt_new(int, 1);
465       int *adst = xbt_new(int, 1);
466       int *arecv = xbt_new(int, 1);
467       *asrc = requests[i]->src;
468       *adst = requests[i]->dst;
469       *arecv = requests[i]->recv;
470       xbt_dynar_insert_at(srcs, i, asrc);
471       xbt_dynar_insert_at(dsts, i, adst);
472       xbt_dynar_insert_at(recvs, i, arecv);
473       xbt_free(asrc);
474       xbt_free(adst);
475       xbt_free(arecv);
476     }else {
477       int *t = xbt_new(int, 1);
478       xbt_dynar_insert_at(srcs, i, t);
479       xbt_dynar_insert_at(dsts, i, t);
480       xbt_dynar_insert_at(recvs, i, t);
481       xbt_free(t);
482     }
483    }
484    int rank_traced = smpi_process_index();
485    instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
486    extra->type = TRACING_WAITALL;
487    extra->send_size=count_requests;
488    TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__,extra);
489  #endif
490
491     smpi_mpi_waitall(count_requests, requests, status);
492
493   #ifdef HAVE_TRACING
494    for (i = 0; i < count_requests; i++) {
495     int src_traced, dst_traced, is_wait_for_receive;
496     xbt_dynar_get_cpy(srcs, i, &src_traced);
497     xbt_dynar_get_cpy(dsts, i, &dst_traced);
498     xbt_dynar_get_cpy(recvs, i, &is_wait_for_receive);
499     if (is_wait_for_receive) {
500       TRACE_smpi_recv(rank_traced, src_traced, dst_traced);
501     }
502    }
503    TRACE_smpi_ptp_out(rank_traced, -1, -1, __FUNCTION__);
504    //clean-up of dynars
505    xbt_dynar_free(&srcs);
506    xbt_dynar_free(&dsts);
507    xbt_dynar_free(&recvs);
508   #endif
509
510    int freedrank=smpi_process_index();
511    xbt_dynar_free_container(&(reqq[freedrank]));
512    reqq[freedrank]=xbt_dynar_new(sizeof(MPI_Request),&xbt_free_ref);
513   }
514   log_timed_action (action, clock);
515 }
516
517 static void action_barrier(const char *const *action){
518   double clock = smpi_process_simulated_elapsed();
519 #ifdef HAVE_TRACING
520   int rank = smpi_process_index();
521   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
522   extra->type = TRACING_BARRIER;
523   TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
524 #endif
525   mpi_coll_barrier_fun(MPI_COMM_WORLD);
526 #ifdef HAVE_TRACING
527   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
528 #endif
529
530   log_timed_action (action, clock);
531 }
532
533
534 static void action_bcast(const char *const *action)
535 {
536   CHECK_ACTION_PARAMS(action, 1, 2);
537   double size = parse_double(action[2]);
538   double clock = smpi_process_simulated_elapsed();
539   int root=0;
540   /*
541    * Initialize MPI_CURRENT_TYPE in order to decrease
542    * the number of the checks
543    * */
544   MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;  
545
546   if(action[3]) {
547     root= atoi(action[3]);
548     if(action[4]) {
549       MPI_CURRENT_TYPE=decode_datatype(action[4]);   
550     }
551   }
552
553 #ifdef HAVE_TRACING
554   int rank = smpi_process_index();
555   int root_traced = smpi_group_index(smpi_comm_group(MPI_COMM_WORLD), root);
556
557   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
558   extra->type = TRACING_BCAST;
559   extra->send_size = size;
560   extra->root = root_traced;
561   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
562   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
563
564 #endif
565     void *sendbuf = smpi_get_tmp_sendbuffer(size* smpi_datatype_size(MPI_CURRENT_TYPE));
566   mpi_coll_bcast_fun(sendbuf, size, MPI_CURRENT_TYPE, root, MPI_COMM_WORLD);
567 #ifdef HAVE_TRACING
568   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
569 #endif
570   log_timed_action (action, clock);
571 }
572
573 static void action_reduce(const char *const *action)
574 {
575   CHECK_ACTION_PARAMS(action, 2, 2);
576   double comm_size = parse_double(action[2]);
577   double comp_size = parse_double(action[3]);
578   double clock = smpi_process_simulated_elapsed();
579   int root=0;
580   MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
581
582   if(action[4]) {
583     root= atoi(action[4]);
584     if(action[5]) {
585       MPI_CURRENT_TYPE=decode_datatype(action[5]);
586     }
587   }
588   
589   
590
591 #ifdef HAVE_TRACING
592   int rank = smpi_process_index();
593   int root_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), root);
594   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
595   extra->type = TRACING_REDUCE;
596   extra->send_size = comm_size;
597   extra->comp_size = comp_size;
598   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
599   extra->root = root_traced;
600
601   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__,extra);
602 #endif
603     void *recvbuf = smpi_get_tmp_sendbuffer(comm_size* smpi_datatype_size(MPI_CURRENT_TYPE));
604     void *sendbuf = smpi_get_tmp_sendbuffer(comm_size* smpi_datatype_size(MPI_CURRENT_TYPE));
605    mpi_coll_reduce_fun(sendbuf, recvbuf, comm_size, MPI_CURRENT_TYPE, MPI_OP_NULL, root, MPI_COMM_WORLD);
606    smpi_execute_flops(comp_size);
607 #ifdef HAVE_TRACING
608   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
609 #endif
610   log_timed_action (action, clock);
611 }
612
613 static void action_allReduce(const char *const *action) {
614   CHECK_ACTION_PARAMS(action, 2, 1);
615   double comm_size = parse_double(action[2]);
616   double comp_size = parse_double(action[3]);
617
618   if(action[4]) MPI_CURRENT_TYPE=decode_datatype(action[4]);
619   else MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
620
621   double clock = smpi_process_simulated_elapsed();
622 #ifdef HAVE_TRACING
623   int rank = smpi_process_index();
624   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
625   extra->type = TRACING_ALLREDUCE;
626   extra->send_size = comm_size;
627   extra->comp_size = comp_size;
628   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
629
630   TRACE_smpi_collective_in(rank, -1, __FUNCTION__,extra);
631 #endif
632     void *recvbuf = smpi_get_tmp_sendbuffer(comm_size* smpi_datatype_size(MPI_CURRENT_TYPE));
633     void *sendbuf = smpi_get_tmp_sendbuffer(comm_size* smpi_datatype_size(MPI_CURRENT_TYPE));
634   mpi_coll_allreduce_fun(sendbuf, recvbuf, comm_size, MPI_CURRENT_TYPE, MPI_OP_NULL, MPI_COMM_WORLD);
635   smpi_execute_flops(comp_size);
636 #ifdef HAVE_TRACING
637   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
638 #endif
639   log_timed_action (action, clock);
640 }
641
642 static void action_allToAll(const char *const *action) {
643   double clock = smpi_process_simulated_elapsed();
644   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
645   int send_size = parse_double(action[2]);
646   int recv_size = parse_double(action[3]);
647   MPI_Datatype MPI_CURRENT_TYPE2;
648
649   if(action[4]) {
650     MPI_CURRENT_TYPE=decode_datatype(action[4]);
651     MPI_CURRENT_TYPE2=decode_datatype(action[5]);
652   }
653   else {
654     MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
655     MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
656   }
657   void *send = smpi_get_tmp_sendbuffer(send_size*comm_size* smpi_datatype_size(MPI_CURRENT_TYPE));
658   void *recv = smpi_get_tmp_recvbuffer(recv_size*comm_size* smpi_datatype_size(MPI_CURRENT_TYPE2));
659
660 #ifdef HAVE_TRACING
661   int rank = smpi_process_index();
662   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
663   extra->type = TRACING_ALLTOALL;
664   extra->send_size = send_size;
665   extra->recv_size = recv_size;
666   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
667   extra->datatype2 = encode_datatype(MPI_CURRENT_TYPE2);
668
669   TRACE_smpi_collective_in(rank, -1, __FUNCTION__,extra);
670 #endif
671
672   mpi_coll_alltoall_fun(send, send_size, MPI_CURRENT_TYPE, recv, recv_size, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
673
674 #ifdef HAVE_TRACING
675   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
676 #endif
677   log_timed_action (action, clock);
678
679 }
680
681
682 static void action_gather(const char *const *action) {
683   /*
684  The structure of the gather action for the rank 0 (total 4 processes) 
685  is the following:   
686  0 gather 68 68 0 0 0
687
688   where: 
689   1) 68 is the sendcounts
690   2) 68 is the recvcounts
691   3) 0 is the root node
692   4) 0 is the send datatype id, see decode_datatype()
693   5) 0 is the recv datatype id, see decode_datatype()
694   */
695   CHECK_ACTION_PARAMS(action, 2, 3);
696   double clock = smpi_process_simulated_elapsed();
697   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
698   int send_size = parse_double(action[2]);
699   int recv_size = parse_double(action[3]);
700   MPI_Datatype MPI_CURRENT_TYPE2;
701   if(action[5]) {
702     MPI_CURRENT_TYPE=decode_datatype(action[5]);
703     MPI_CURRENT_TYPE2=decode_datatype(action[6]);
704   } else {
705     MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
706     MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
707   }
708   void *send = smpi_get_tmp_sendbuffer(send_size* smpi_datatype_size(MPI_CURRENT_TYPE));
709   void *recv = NULL;
710   int root=0;
711   if(action[4])
712     root=atoi(action[4]);
713   int rank = smpi_comm_rank(MPI_COMM_WORLD);
714
715   if(rank==root)
716     recv = smpi_get_tmp_recvbuffer(recv_size*comm_size* smpi_datatype_size(MPI_CURRENT_TYPE2));
717
718 #ifdef HAVE_TRACING
719   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
720   extra->type = TRACING_GATHER;
721   extra->send_size = send_size;
722   extra->recv_size = recv_size;
723   extra->root = root;
724   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
725   extra->datatype2 = encode_datatype(MPI_CURRENT_TYPE2);
726
727   TRACE_smpi_collective_in(smpi_process_index(), root, __FUNCTION__, extra);
728 #endif
729   mpi_coll_gather_fun(send, send_size, MPI_CURRENT_TYPE,
730                 recv, recv_size, MPI_CURRENT_TYPE2,
731                 root, MPI_COMM_WORLD);
732
733 #ifdef HAVE_TRACING
734   TRACE_smpi_collective_out(smpi_process_index(), -1, __FUNCTION__);
735 #endif
736   log_timed_action (action, clock);
737
738 }
739
740
741
742 static void action_gatherv(const char *const *action) {
743   /*
744  The structure of the gatherv action for the rank 0 (total 4 processes)
745  is the following:
746  0 gather 68 68 10 10 10 0 0 0
747
748   where:
749   1) 68 is the sendcount
750   2) 68 10 10 10 is the recvcounts
751   3) 0 is the root node
752   4) 0 is the send datatype id, see decode_datatype()
753   5) 0 is the recv datatype id, see decode_datatype()
754   */
755
756   double clock = smpi_process_simulated_elapsed();
757   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
758   CHECK_ACTION_PARAMS(action, comm_size+1, 2);
759   int send_size = parse_double(action[2]);
760   int *disps = xbt_new0(int, comm_size);
761   int *recvcounts = xbt_new0(int, comm_size);
762   int i=0,recv_sum=0;
763
764   MPI_Datatype MPI_CURRENT_TYPE2;
765   if(action[4+comm_size]) {
766     MPI_CURRENT_TYPE=decode_datatype(action[4+comm_size]);
767     MPI_CURRENT_TYPE2=decode_datatype(action[5+comm_size]);
768   } else {
769     MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
770     MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
771   }
772   void *send = smpi_get_tmp_sendbuffer(send_size* smpi_datatype_size(MPI_CURRENT_TYPE));
773   void *recv = NULL;
774   for(i=0;i<comm_size;i++) {
775     recvcounts[i] = atoi(action[i+3]);
776     recv_sum=recv_sum+recvcounts[i];
777     disps[i] = 0;
778   }
779
780   int root=atoi(action[3+comm_size]);
781   int rank = smpi_comm_rank(MPI_COMM_WORLD);;
782
783   if(rank==root)
784     recv = smpi_get_tmp_recvbuffer(recv_sum* smpi_datatype_size(MPI_CURRENT_TYPE2));
785
786 #ifdef HAVE_TRACING
787   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
788   extra->type = TRACING_GATHERV;
789   extra->send_size = send_size;
790   extra->recvcounts= xbt_malloc(comm_size*sizeof(int));
791   for(i=0; i< comm_size; i++)//copy data to avoid bad free
792     extra->recvcounts[i] = recvcounts[i];
793   extra->root = root;
794   extra->num_processes = comm_size;
795   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
796   extra->datatype2 = encode_datatype(MPI_CURRENT_TYPE2);
797
798   TRACE_smpi_collective_in(smpi_process_index(), root, __FUNCTION__, extra);
799 #endif
800 smpi_mpi_gatherv(send, send_size, MPI_CURRENT_TYPE,
801                 recv, recvcounts, disps, MPI_CURRENT_TYPE2,
802                 root, MPI_COMM_WORLD);
803
804 #ifdef HAVE_TRACING
805   TRACE_smpi_collective_out(smpi_process_index(), -1, __FUNCTION__);
806 #endif
807
808   log_timed_action (action, clock);
809   xbt_free(recvcounts);
810   xbt_free(disps);
811 }
812
813 static void action_reducescatter(const char *const *action) {
814
815     /*
816  The structure of the reducescatter action for the rank 0 (total 4 processes) 
817  is the following:   
818 0 reduceScatter 275427 275427 275427 204020 11346849 0
819
820   where: 
821   1) The first four values after the name of the action declare the recvcounts array
822   2) The value 11346849 is the amount of instructions
823   3) The last value corresponds to the datatype, see decode_datatype().
824
825   We analyze a MPI_Reduce_scatter call to one MPI_Reduce and one MPI_Scatterv.
826
827    */
828
829   double clock = smpi_process_simulated_elapsed();
830   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
831   CHECK_ACTION_PARAMS(action, comm_size+1, 1);
832   int comp_size = parse_double(action[2+comm_size]);
833   int *recvcounts = xbt_new0(int, comm_size);  
834   int *disps = xbt_new0(int, comm_size);  
835   int i=0;
836   int rank = smpi_process_index();
837   int size = 0;
838   if(action[3+comm_size])
839     MPI_CURRENT_TYPE=decode_datatype(action[3+comm_size]);
840   else
841     MPI_CURRENT_TYPE= MPI_DEFAULT_TYPE;
842
843   for(i=0;i<comm_size;i++) {
844     recvcounts[i] = atoi(action[i+2]);
845     disps[i] = 0;
846     size+=recvcounts[i];
847   }
848
849 #ifdef HAVE_TRACING
850   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
851   extra->type = TRACING_REDUCE_SCATTER;
852   extra->send_size = 0;
853   extra->recvcounts= xbt_malloc(comm_size*sizeof(int));
854   for(i=0; i< comm_size; i++)//copy data to avoid bad free
855     extra->recvcounts[i] = recvcounts[i];
856   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
857   extra->comp_size = comp_size;
858   extra->num_processes = comm_size;
859
860   TRACE_smpi_collective_in(rank, -1, __FUNCTION__,extra);
861 #endif
862   void *sendbuf = smpi_get_tmp_sendbuffer(size* smpi_datatype_size(MPI_CURRENT_TYPE));
863    void *recvbuf = smpi_get_tmp_recvbuffer(size* smpi_datatype_size(MPI_CURRENT_TYPE));
864    
865    mpi_coll_reduce_scatter_fun(sendbuf, recvbuf, recvcounts, MPI_CURRENT_TYPE, MPI_OP_NULL,
866        MPI_COMM_WORLD);
867    smpi_execute_flops(comp_size);
868
869
870 #ifdef HAVE_TRACING
871   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
872 #endif
873   xbt_free(recvcounts);
874   xbt_free(disps);
875   log_timed_action (action, clock);
876 }
877
878 static void action_allgather(const char *const *action) {
879   /*
880  The structure of the allgather action for the rank 0 (total 4 processes) 
881  is the following:   
882   0 allGather 275427 275427
883
884   where: 
885   1) 275427 is the sendcount
886   2) 275427 is the recvcount
887   3) No more values mean that the datatype for sent and receive buffer
888   is the default one, see decode_datatype().
889
890    */
891
892   double clock = smpi_process_simulated_elapsed();
893
894   CHECK_ACTION_PARAMS(action, 2, 2);
895   int sendcount=atoi(action[2]); 
896   int recvcount=atoi(action[3]); 
897
898   MPI_Datatype MPI_CURRENT_TYPE2;
899
900   if(action[4]) {
901     MPI_CURRENT_TYPE = decode_datatype(action[3]);
902     MPI_CURRENT_TYPE2 = decode_datatype(action[4]);
903   } else {
904     MPI_CURRENT_TYPE = MPI_DEFAULT_TYPE;
905     MPI_CURRENT_TYPE2 = MPI_DEFAULT_TYPE;    
906   }
907   void *sendbuf = smpi_get_tmp_sendbuffer(sendcount* smpi_datatype_size(MPI_CURRENT_TYPE));
908   void *recvbuf = smpi_get_tmp_recvbuffer(recvcount* smpi_datatype_size(MPI_CURRENT_TYPE2));
909
910 #ifdef HAVE_TRACING
911   int rank = smpi_process_index();
912   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
913   extra->type = TRACING_ALLGATHER;
914   extra->send_size = sendcount;
915   extra->recv_size= recvcount;
916   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
917   extra->datatype2 = encode_datatype(MPI_CURRENT_TYPE2);
918   extra->num_processes = smpi_comm_size(MPI_COMM_WORLD);
919
920   TRACE_smpi_collective_in(rank, -1, __FUNCTION__,extra);
921 #endif
922
923   mpi_coll_allgather_fun(sendbuf, sendcount, MPI_CURRENT_TYPE, recvbuf, recvcount, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
924
925 #ifdef HAVE_TRACING
926   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
927 #endif
928
929   log_timed_action (action, clock);
930 }
931
932 static void action_allgatherv(const char *const *action) {
933
934   /*
935  The structure of the allgatherv action for the rank 0 (total 4 processes) 
936  is the following:   
937 0 allGatherV 275427 275427 275427 275427 204020
938
939   where: 
940   1) 275427 is the sendcount
941   2) The next four elements declare the recvcounts array
942   3) No more values mean that the datatype for sent and receive buffer
943   is the default one, see decode_datatype().
944
945    */
946
947   double clock = smpi_process_simulated_elapsed();
948
949   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
950   CHECK_ACTION_PARAMS(action, comm_size+1, 2);
951   int i=0;
952   int sendcount=atoi(action[2]);
953   int *recvcounts = xbt_new0(int, comm_size);  
954   int *disps = xbt_new0(int, comm_size);  
955   int recv_sum=0;  
956   MPI_Datatype MPI_CURRENT_TYPE2;
957
958   if(action[3+comm_size]) {
959     MPI_CURRENT_TYPE = decode_datatype(action[3+comm_size]);
960     MPI_CURRENT_TYPE2 = decode_datatype(action[4+comm_size]);
961   } else {
962     MPI_CURRENT_TYPE = MPI_DEFAULT_TYPE;
963     MPI_CURRENT_TYPE2 = MPI_DEFAULT_TYPE;    
964   }
965   void *sendbuf = smpi_get_tmp_sendbuffer(sendcount* smpi_datatype_size(MPI_CURRENT_TYPE));
966
967   for(i=0;i<comm_size;i++) {
968     recvcounts[i] = atoi(action[i+3]);
969     recv_sum=recv_sum+recvcounts[i];
970   }
971   void *recvbuf = smpi_get_tmp_recvbuffer(recv_sum* smpi_datatype_size(MPI_CURRENT_TYPE2));
972
973 #ifdef HAVE_TRACING
974   int rank = smpi_process_index();
975   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
976   extra->type = TRACING_ALLGATHERV;
977   extra->send_size = sendcount;
978   extra->recvcounts= xbt_malloc(comm_size*sizeof(int));
979   for(i=0; i< comm_size; i++)//copy data to avoid bad free
980     extra->recvcounts[i] = recvcounts[i];
981   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
982   extra->datatype2 = encode_datatype(MPI_CURRENT_TYPE2);
983   extra->num_processes = comm_size;
984
985   TRACE_smpi_collective_in(rank, -1, __FUNCTION__,extra);
986 #endif
987
988   mpi_coll_allgatherv_fun(sendbuf, sendcount, MPI_CURRENT_TYPE, recvbuf, recvcounts, disps, MPI_CURRENT_TYPE2, MPI_COMM_WORLD);
989
990 #ifdef HAVE_TRACING
991   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
992 #endif
993
994   log_timed_action (action, clock);
995   xbt_free(recvcounts);
996   xbt_free(disps);
997 }
998
999 static void action_allToAllv(const char *const *action) {
1000   /*
1001  The structure of the allToAllV action for the rank 0 (total 4 processes) 
1002  is the following:   
1003   0 allToAllV 100 1 7 10 12 100 1 70 10 5
1004
1005   where: 
1006   1) 100 is the size of the send buffer *sizeof(int),
1007   2) 1 7 10 12 is the sendcounts array
1008   3) 100*sizeof(int) is the size of the receiver buffer
1009   4)  1 70 10 5 is the recvcounts array
1010
1011    */
1012
1013
1014   double clock = smpi_process_simulated_elapsed();
1015
1016   int comm_size = smpi_comm_size(MPI_COMM_WORLD);
1017   CHECK_ACTION_PARAMS(action, 2*comm_size+2, 2);
1018   int send_buf_size=0,recv_buf_size=0,i=0;
1019   int *sendcounts = xbt_new0(int, comm_size);  
1020   int *recvcounts = xbt_new0(int, comm_size);  
1021   int *senddisps = xbt_new0(int, comm_size);  
1022   int *recvdisps = xbt_new0(int, comm_size);  
1023
1024   MPI_Datatype MPI_CURRENT_TYPE2;
1025
1026   send_buf_size=parse_double(action[2]);
1027   recv_buf_size=parse_double(action[3+comm_size]);
1028   if(action[4+2*comm_size]) {
1029     MPI_CURRENT_TYPE=decode_datatype(action[4+2*comm_size]);
1030     MPI_CURRENT_TYPE2=decode_datatype(action[5+2*comm_size]);
1031   }
1032   else {
1033       MPI_CURRENT_TYPE=MPI_DEFAULT_TYPE;
1034       MPI_CURRENT_TYPE2=MPI_DEFAULT_TYPE;
1035   }
1036
1037   void *sendbuf = smpi_get_tmp_sendbuffer(send_buf_size* smpi_datatype_size(MPI_CURRENT_TYPE));
1038   void *recvbuf  = smpi_get_tmp_recvbuffer(recv_buf_size* smpi_datatype_size(MPI_CURRENT_TYPE2));
1039
1040   for(i=0;i<comm_size;i++) {
1041     sendcounts[i] = atoi(action[i+3]);
1042     recvcounts[i] = atoi(action[i+4+comm_size]);
1043   }
1044
1045
1046 #ifdef HAVE_TRACING
1047   int rank = smpi_process_index();
1048   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1049   extra->type = TRACING_ALLTOALLV;
1050   extra->recvcounts= xbt_malloc(comm_size*sizeof(int));
1051   extra->sendcounts= xbt_malloc(comm_size*sizeof(int));
1052   extra->num_processes = comm_size;
1053
1054   for(i=0; i< comm_size; i++){//copy data to avoid bad free
1055     extra->send_size += sendcounts[i];
1056     extra->sendcounts[i] = sendcounts[i];
1057     extra->recv_size += recvcounts[i];
1058     extra->recvcounts[i] = recvcounts[i];
1059   }
1060   extra->datatype1 = encode_datatype(MPI_CURRENT_TYPE);
1061   extra->datatype2 = encode_datatype(MPI_CURRENT_TYPE2);
1062
1063   TRACE_smpi_collective_in(rank, -1, __FUNCTION__,extra);
1064 #endif
1065   mpi_coll_alltoallv_fun(sendbuf, sendcounts, senddisps, MPI_CURRENT_TYPE,
1066                                recvbuf, recvcounts, recvdisps, MPI_CURRENT_TYPE,
1067                                MPI_COMM_WORLD);
1068 #ifdef HAVE_TRACING
1069   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1070 #endif
1071
1072   log_timed_action (action, clock);
1073   xbt_free(sendcounts);
1074   xbt_free(recvcounts);
1075   xbt_free(senddisps);
1076   xbt_free(recvdisps);
1077 }
1078
1079 void smpi_replay_init(int *argc, char***argv){
1080   smpi_process_init(argc, argv);
1081   smpi_process_mark_as_initialized();
1082   smpi_process_set_replaying(1);
1083 #ifdef HAVE_TRACING
1084   int rank = smpi_process_index();
1085   TRACE_smpi_init(rank);
1086   TRACE_smpi_computing_init(rank);
1087   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1088   extra->type = TRACING_INIT;
1089   TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
1090   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1091 #endif
1092
1093   if (!smpi_process_index()){
1094     _xbt_replay_action_init();
1095     xbt_replay_action_register("init",       action_init);
1096     xbt_replay_action_register("finalize",   action_finalize);
1097     xbt_replay_action_register("comm_size",  action_comm_size);
1098     xbt_replay_action_register("comm_split", action_comm_split);
1099     xbt_replay_action_register("comm_dup",   action_comm_dup);
1100     xbt_replay_action_register("send",       action_send);
1101     xbt_replay_action_register("Isend",      action_Isend);
1102     xbt_replay_action_register("recv",       action_recv);
1103     xbt_replay_action_register("Irecv",      action_Irecv);
1104     xbt_replay_action_register("test",       action_test);
1105     xbt_replay_action_register("wait",       action_wait);
1106     xbt_replay_action_register("waitAll",    action_waitall);
1107     xbt_replay_action_register("barrier",    action_barrier);
1108     xbt_replay_action_register("bcast",      action_bcast);
1109     xbt_replay_action_register("reduce",     action_reduce);
1110     xbt_replay_action_register("allReduce",  action_allReduce);
1111     xbt_replay_action_register("allToAll",   action_allToAll);
1112     xbt_replay_action_register("allToAllV",  action_allToAllv);
1113     xbt_replay_action_register("gather",  action_gather);
1114     xbt_replay_action_register("gatherV",  action_gatherv);
1115     xbt_replay_action_register("allGather",  action_allgather);
1116     xbt_replay_action_register("allGatherV",  action_allgatherv);
1117     xbt_replay_action_register("reduceScatter",  action_reducescatter);
1118     xbt_replay_action_register("compute",    action_compute);
1119   }
1120   
1121   //if we have a delayed start, sleep here.
1122   if(*argc>2){
1123     char *endptr;
1124     double value = strtod((*argv)[2], &endptr);
1125     if (*endptr != '\0')
1126       THROWF(unknown_error, 0, "%s is not a double", (*argv)[2]);
1127     XBT_VERB("Delayed start for instance - Sleeping for %f flops ",value );
1128     smpi_execute_flops(value);
1129   }
1130   xbt_replay_action_runner(*argc, *argv);
1131 }
1132
1133 int smpi_replay_finalize(){
1134   double sim_time= 1.;
1135   /* One active process will stop. Decrease the counter*/
1136   XBT_DEBUG("There are %lu elements in reqq[*]",
1137             xbt_dynar_length(reqq[smpi_process_index()]));
1138   if (!xbt_dynar_is_empty(reqq[smpi_process_index()])){
1139     int count_requests=xbt_dynar_length(reqq[smpi_process_index()]);
1140     MPI_Request requests[count_requests];
1141     MPI_Status status[count_requests];
1142     unsigned int i;
1143
1144     xbt_dynar_foreach(reqq[smpi_process_index()],i,requests[i]);
1145     smpi_mpi_waitall(count_requests, requests, status);
1146     active_processes--;
1147   } else {
1148     active_processes--;
1149   }
1150
1151   if(!active_processes){
1152     /* Last process alive speaking */
1153     /* end the simulated timer */
1154     sim_time = smpi_process_simulated_elapsed();
1155   }
1156   
1157
1158   xbt_dynar_free_container(&(reqq[smpi_process_index()]));
1159
1160   if(!active_processes){
1161     XBT_INFO("Simulation time %f", sim_time);
1162     _xbt_replay_action_exit();
1163     xbt_free(sendbuffer);
1164     xbt_free(recvbuffer);
1165     xbt_free(reqq);
1166     reqq = NULL;
1167   }
1168   
1169
1170 #ifdef HAVE_TRACING
1171   int rank = smpi_process_index();
1172   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1173   extra->type = TRACING_FINALIZE;
1174   TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
1175 #endif
1176   smpi_process_finalize();
1177 #ifdef HAVE_TRACING
1178   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1179   TRACE_smpi_finalize(smpi_process_index());
1180 #endif
1181   smpi_process_destroy();
1182   return MPI_SUCCESS;
1183 }