Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add MPI_Win_post, MPI_Win_start, MPI_Win_complete, and MPI_Win_wait support.
[simgrid.git] / src / smpi / instr_smpi.c
1 /* Copyright (c) 2010, 2012-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 <ctype.h>
9 #include <wchar.h>
10 #include <stdarg.h>
11 #include <simgrid/sg_config.h>
12
13
14 #ifdef HAVE_TRACING
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
17
18 static xbt_dict_t keys;
19
20 static const char *smpi_colors[] ={
21     "recv",     "1 0 0",
22     "irecv",    "1 0.52 0.52",
23     "send",     "0 0 1",
24     "isend",    "0.52 0.52 1",
25     "sendrecv", "0 1 1",
26     "wait",     "1 1 0",
27     "waitall",  "0.78 0.78 0",
28     "waitany",  "0.78 0.78 0.58",
29     "test",     "0.52 0.52 0",
30
31     "allgather",     "1 0 0",
32     "allgatherv",    "1 0.52 0.52",
33     "allreduce",     "1 0 1",
34     "alltoall",      "0.52 0 1",
35     "alltoallv",     "0.78 0.52 1",
36     "barrier",       "0 0.78 0.78",
37     "bcast",         "0 0.78 0.39",
38     "gather",        "1 1 0",
39     "gatherv",       "1 1 0.52",
40     "reduce",        "0 1 0",
41     "reducescatter", "0.52 1 0.52",
42     "scan",          "1 0.58 0.23",
43     "exscan",          "1 0.54 0.25",
44     "scatterv",      "0.52 0 0.52",
45     "scatter",       "1 0.74 0.54",
46
47     "computing",     "0 1 1",
48     "sleeping",      "0 0.5 0.5",
49
50     "init",       "0 1 0",
51     "finalize",     "0 1 0",
52
53     "put",       "0.3 1 0",
54     "get",       "0 1 0.3",
55     "accumulate",       "1 0.3 0",
56     "win_fence",       "1 0 0.3",
57     "win_post",       "1 0 0.8",
58     "win_wait",       "1 0.8 0",
59     "win_start",       "0.8 0 1",
60     "win_complete",       "0.8 1 0",
61     NULL, NULL,
62 };
63
64 static char *str_tolower (const char *str)
65 {
66   char *ret = xbt_strdup (str);
67   int i, n = strlen (ret);
68   for (i = 0; i < n; i++)
69     ret[i] = tolower (str[i]);
70   return ret;
71 }
72
73 static const char *instr_find_color (const char *state)
74 {
75   char *target = str_tolower (state);
76   const char *ret = NULL;
77   const char *current;
78   unsigned int i = 0;
79   while ((current = smpi_colors[i])){
80     if (strcmp (state, current) == 0){ ret = smpi_colors[i+1]; break; } //exact match
81     if (strstr(target, current)) { ret = smpi_colors[i+1]; break; }; //as substring
82     i+=2;
83   }
84   free (target);
85   return ret;
86 }
87
88
89 static char *smpi_container(int rank, char *container, int n)
90 {
91   snprintf(container, n, "rank-%d", rank);
92   return container;
93 }
94
95 static char *TRACE_smpi_get_key(int src, int dst, char *key, int n);
96
97
98 static char *TRACE_smpi_put_key(int src, int dst, char *key, int n)
99 {
100   //get the dynar for src#dst
101   char aux[INSTR_DEFAULT_STR_SIZE];
102   snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d", src, dst);
103   xbt_dynar_t d = xbt_dict_get_or_null(keys, aux);
104
105
106   if(!xbt_dynar_is_empty(d)){
107     //receive was already pushed, perform a get instead
108     TRACE_smpi_get_key(src , dst, key ,n);
109     return key;
110   }
111
112   if (d == NULL) {
113     d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
114     xbt_dict_set(keys, aux, d, NULL);
115   }
116
117   //generate the key
118   static unsigned long long counter = 0;
119
120   snprintf(key, n, "%d_%d_%llu", src, dst, counter++);
121
122   //push it
123   char *a = (char*)xbt_strdup(key);
124   xbt_dynar_push_as(d, char *, a);
125
126   return key;
127 }
128
129 static char *TRACE_smpi_get_key(int src, int dst, char *key, int n)
130 {
131   char aux[INSTR_DEFAULT_STR_SIZE];
132   snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d", src, dst);
133   xbt_dynar_t d = xbt_dict_get_or_null(keys, aux);
134
135  // xbt_assert(!xbt_dynar_is_empty(d),
136  //     "Trying to get a link key (for message reception) that has no corresponding send (%s).", __FUNCTION__);
137
138   // sometimes the receive may be posted before the send
139   if(xbt_dynar_is_empty(d)){
140       TRACE_smpi_put_key(src, dst, key, n);
141       return key;
142   }
143
144   char *s = xbt_dynar_get_as (d, 0, char *);
145   snprintf (key, n, "%s", s);
146   xbt_dynar_remove_at (d, 0, NULL);
147   return key;
148 }
149
150 static xbt_dict_t process_category;
151
152 static void cleanup_extra_data (instr_extra_data extra){
153   if(extra!=NULL){
154     if(extra->sendcounts!=NULL)
155       xbt_free(extra->sendcounts);
156     if(extra->recvcounts!=NULL)
157       xbt_free(extra->recvcounts);
158     xbt_free(extra);
159   }
160 }
161
162 void TRACE_internal_smpi_set_category (const char *category)
163 {
164   if (!TRACE_smpi_is_enabled()) return;
165
166   //declare category
167   TRACE_category (category);
168
169   char processid[INSTR_DEFAULT_STR_SIZE];
170   snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
171   if (xbt_dict_get_or_null (process_category, processid))
172     xbt_dict_remove (process_category, processid);
173   if (category != NULL)
174     xbt_dict_set (process_category, processid, xbt_strdup(category), NULL);
175 }
176
177 const char *TRACE_internal_smpi_get_category (void)
178 {
179   if (!TRACE_smpi_is_enabled()) return NULL;
180
181   char processid[INSTR_DEFAULT_STR_SIZE];
182   snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
183   return xbt_dict_get_or_null (process_category, processid);
184 }
185
186 void TRACE_smpi_alloc()
187 {
188   keys = xbt_dict_new_homogeneous(xbt_dynar_free_voidp);
189   process_category = xbt_dict_new_homogeneous(xbt_free_f);
190 }
191
192 void TRACE_smpi_release(void)
193 {
194   xbt_dict_free(&keys);
195   xbt_dict_free(&process_category);
196 }
197
198 void TRACE_smpi_init(int rank)
199 {
200   if (!TRACE_smpi_is_enabled()) return;
201
202   char str[INSTR_DEFAULT_STR_SIZE];
203   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
204
205   container_t father;
206   if (TRACE_smpi_is_grouped()){
207     father = PJ_container_get (SIMIX_host_self_get_name());
208   }else{
209     father = PJ_container_get_root ();
210   }
211   xbt_assert(father!=NULL,
212       "Could not find a parent for mpi rank %s at function %s", str, __FUNCTION__);
213   PJ_container_new(str, INSTR_SMPI, father);
214 }
215
216 void TRACE_smpi_finalize(int rank)
217 {
218   if (!TRACE_smpi_is_enabled()) return;
219
220   char str[INSTR_DEFAULT_STR_SIZE];
221   container_t container = PJ_container_get(smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE));
222   PJ_container_remove_from_parent (container);
223   PJ_container_free (container);
224 }
225
226 void TRACE_smpi_collective_in(int rank, int root, const char *operation, instr_extra_data extra)
227 {
228   if (!TRACE_smpi_is_enabled()) {
229       cleanup_extra_data(extra);
230       return;
231   }
232
233   char str[INSTR_DEFAULT_STR_SIZE];
234   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
235   container_t container = PJ_container_get (str);
236   type_t type = PJ_type_get ("MPI_STATE", container->type);
237   const char *color = instr_find_color (operation);
238   val_t value = PJ_value_get_or_new (operation, color, type);
239    new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
240 }
241
242
243 void TRACE_smpi_collective_out(int rank, int root, const char *operation)
244 {
245   if (!TRACE_smpi_is_enabled()) return;
246
247   char str[INSTR_DEFAULT_STR_SIZE];
248   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
249   container_t container = PJ_container_get (str);
250   type_t type = PJ_type_get ("MPI_STATE", container->type);
251
252   new_pajePopState (SIMIX_get_clock(), container, type);
253 }
254
255 void TRACE_smpi_computing_init(int rank)
256 {
257  //first use, initialize the color in the trace
258  //TODO : check with lucas and Pierre how to generalize this approach
259   //to avoid unnecessary access to the color array
260   if (!TRACE_smpi_is_enabled() || !TRACE_smpi_is_computing()) return;
261
262   char str[INSTR_DEFAULT_STR_SIZE];
263   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
264   container_t container = PJ_container_get (str);
265   type_t type = PJ_type_get ("MPI_STATE", container->type);
266   const char *color = instr_find_color ("computing");
267   val_t value = PJ_value_get_or_new ("computing", color, type);
268   new_pajePushState (SIMIX_get_clock(), container, type, value);
269 }
270
271 void TRACE_smpi_computing_in(int rank, instr_extra_data extra)
272 {
273   //do not forget to set the color first, otherwise this will explode
274   if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_computing()) {
275       cleanup_extra_data(extra);
276       return;
277   }
278
279   char str[INSTR_DEFAULT_STR_SIZE];
280   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
281   container_t container = PJ_container_get (str);
282   type_t type = PJ_type_get ("MPI_STATE", container->type);
283   val_t value = PJ_value_get_or_new ("computing", NULL, type);
284   new_pajePushStateWithExtra  (SIMIX_get_clock(), container, type, value, (void*)extra);
285 }
286
287 void TRACE_smpi_computing_out(int rank)
288 {
289   if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_computing()) return;
290   char str[INSTR_DEFAULT_STR_SIZE];
291   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
292   container_t container = PJ_container_get (str);
293   type_t type = PJ_type_get ("MPI_STATE", container->type);
294   new_pajePopState (SIMIX_get_clock(), container, type);
295 }
296
297 void TRACE_smpi_sleeping_init(int rank)
298 {
299  //first use, initialize the color in the trace
300  //TODO : check with lucas and Pierre how to generalize this approach
301   //to avoid unnecessary access to the color array
302   if (!TRACE_smpi_is_enabled() || !TRACE_smpi_is_sleeping()) return;
303
304   char str[INSTR_DEFAULT_STR_SIZE];
305   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
306   container_t container = PJ_container_get (str);
307   type_t type = PJ_type_get ("MPI_STATE", container->type);
308   const char *color = instr_find_color ("sleeping");
309   val_t value = PJ_value_get_or_new ("sleeping", color, type);
310   new_pajePushState (SIMIX_get_clock(), container, type, value);
311 }
312
313 void TRACE_smpi_sleeping_in(int rank, instr_extra_data extra)
314 {
315   //do not forget to set the color first, otherwise this will explode
316   if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_sleeping()) {
317       cleanup_extra_data(extra);
318       return;
319   }
320
321   char str[INSTR_DEFAULT_STR_SIZE];
322   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
323   container_t container = PJ_container_get (str);
324   type_t type = PJ_type_get ("MPI_STATE", container->type);
325   val_t value = PJ_value_get_or_new ("sleeping", NULL, type);
326   new_pajePushStateWithExtra  (SIMIX_get_clock(), container, type, value, (void*)extra);
327 }
328
329 void TRACE_smpi_sleeping_out(int rank)
330 {
331   if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_sleeping()) return;
332   char str[INSTR_DEFAULT_STR_SIZE];
333   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
334   container_t container = PJ_container_get (str);
335   type_t type = PJ_type_get ("MPI_STATE", container->type);
336   new_pajePopState (SIMIX_get_clock(), container, type);
337 }
338
339
340 void TRACE_smpi_testing_in(int rank, instr_extra_data extra)
341 {
342   //do not forget to set the color first, otherwise this will explode
343   if (!TRACE_smpi_is_enabled()) {
344       cleanup_extra_data(extra);
345       return;
346   }
347
348   char str[INSTR_DEFAULT_STR_SIZE];
349   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
350   container_t container = PJ_container_get (str);
351   type_t type = PJ_type_get ("MPI_STATE", container->type);
352   val_t value = PJ_value_get_or_new ("test", NULL, type);
353   new_pajePushStateWithExtra  (SIMIX_get_clock(), container, type, value, (void*)extra);
354 }
355
356 void TRACE_smpi_testing_out(int rank)
357 {
358   if (!TRACE_smpi_is_enabled()) return;
359   char str[INSTR_DEFAULT_STR_SIZE];
360   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
361   container_t container = PJ_container_get (str);
362   type_t type = PJ_type_get ("MPI_STATE", container->type);
363   new_pajePopState (SIMIX_get_clock(), container, type);
364 }
365
366 void TRACE_smpi_ptp_in(int rank, int src, int dst, const char *operation, instr_extra_data extra)
367 {
368   if (!TRACE_smpi_is_enabled()) {
369       cleanup_extra_data(extra);
370       return;
371   }
372
373   char str[INSTR_DEFAULT_STR_SIZE];
374   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
375   container_t container = PJ_container_get (str);
376   type_t type = PJ_type_get ("MPI_STATE", container->type);
377   const char *color = instr_find_color (operation);
378   val_t value = PJ_value_get_or_new (operation, color, type);
379   new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
380 }
381
382 void TRACE_smpi_ptp_out(int rank, int src, int dst, const char *operation)
383 {
384   if (!TRACE_smpi_is_enabled()) return;
385
386   char str[INSTR_DEFAULT_STR_SIZE];
387   smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
388   container_t container = PJ_container_get (str);
389   type_t type = PJ_type_get ("MPI_STATE", container->type);
390
391   new_pajePopState (SIMIX_get_clock(), container, type);
392 }
393
394 void TRACE_smpi_send(int rank, int src, int dst, int size)
395 {
396   if (!TRACE_smpi_is_enabled()) return;
397
398   char key[INSTR_DEFAULT_STR_SIZE] = {0};
399   TRACE_smpi_put_key(src, dst, key, INSTR_DEFAULT_STR_SIZE);
400
401   char str[INSTR_DEFAULT_STR_SIZE];
402   smpi_container(src, str, INSTR_DEFAULT_STR_SIZE);
403   container_t container = PJ_container_get (str);
404   type_t type = PJ_type_get ("MPI_LINK", PJ_type_get_root());
405
406   new_pajeStartLinkWithSize (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key, size);
407 }
408
409 void TRACE_smpi_recv(int rank, int src, int dst)
410 {
411   if (!TRACE_smpi_is_enabled()) return;
412
413   char key[INSTR_DEFAULT_STR_SIZE] = {0};
414   TRACE_smpi_get_key(src, dst, key, INSTR_DEFAULT_STR_SIZE);
415
416   char str[INSTR_DEFAULT_STR_SIZE];
417   smpi_container(dst, str, INSTR_DEFAULT_STR_SIZE);
418   container_t container = PJ_container_get (str);
419   type_t type = PJ_type_get ("MPI_LINK", PJ_type_get_root());
420
421   new_pajeEndLink (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key);
422 }
423 #endif /* HAVE_TRACING */