Logo AND Algorithmique Numérique Distribuée

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