1 /* Copyright (c) 2010, 2012-2014. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include <simgrid/sg_config.h>
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
18 static xbt_dict_t keys;
20 static const char *smpi_colors[] ={
22 "irecv", "1 0.52 0.52",
24 "isend", "0.52 0.52 1",
27 "waitall", "0.78 0.78 0",
28 "waitany", "0.78 0.78 0.58",
29 "test", "0.52 0.52 0",
32 "allgatherv", "1 0.52 0.52",
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",
39 "gatherv", "1 1 0.52",
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",
48 "sleeping", "0 0.5 0.5",
55 "accumulate", "1 0.3 0",
60 static char *str_tolower (const char *str)
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]);
69 static const char *instr_find_color (const char *state)
71 char *target = str_tolower (state);
72 const char *ret = NULL;
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
85 static char *smpi_container(int rank, char *container, int n)
87 snprintf(container, n, "rank-%d", rank);
91 static char *TRACE_smpi_get_key(int src, int dst, char *key, int n);
94 static char *TRACE_smpi_put_key(int src, int dst, char *key, int n)
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);
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);
109 d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
110 xbt_dict_set(keys, aux, d, NULL);
114 static unsigned long long counter = 0;
116 snprintf(key, n, "%d_%d_%llu", src, dst, counter++);
119 char *a = (char*)xbt_strdup(key);
120 xbt_dynar_push_as(d, char *, a);
125 static char *TRACE_smpi_get_key(int src, int dst, char *key, int n)
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);
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__);
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);
140 char *s = xbt_dynar_get_as (d, 0, char *);
141 snprintf (key, n, "%s", s);
142 xbt_dynar_remove_at (d, 0, NULL);
146 static xbt_dict_t process_category;
148 static void cleanup_extra_data (instr_extra_data extra){
150 if(extra->sendcounts!=NULL)
151 xbt_free(extra->sendcounts);
152 if(extra->recvcounts!=NULL)
153 xbt_free(extra->recvcounts);
158 void TRACE_internal_smpi_set_category (const char *category)
160 if (!TRACE_smpi_is_enabled()) return;
163 TRACE_category (category);
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);
173 const char *TRACE_internal_smpi_get_category (void)
175 if (!TRACE_smpi_is_enabled()) return NULL;
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);
182 void TRACE_smpi_alloc()
184 keys = xbt_dict_new_homogeneous(xbt_dynar_free_voidp);
185 process_category = xbt_dict_new_homogeneous(xbt_free_f);
188 void TRACE_smpi_release(void)
190 xbt_dict_free(&keys);
191 xbt_dict_free(&process_category);
194 void TRACE_smpi_init(int rank)
196 if (!TRACE_smpi_is_enabled()) return;
198 char str[INSTR_DEFAULT_STR_SIZE];
199 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
202 if (TRACE_smpi_is_grouped()){
203 father = PJ_container_get (SIMIX_host_self_get_name());
205 father = PJ_container_get_root ();
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);
212 void TRACE_smpi_finalize(int rank)
214 if (!TRACE_smpi_is_enabled()) return;
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);
222 void TRACE_smpi_collective_in(int rank, int root, const char *operation, instr_extra_data extra)
224 if (!TRACE_smpi_is_enabled()) {
225 cleanup_extra_data(extra);
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);
239 void TRACE_smpi_collective_out(int rank, int root, const char *operation)
241 if (!TRACE_smpi_is_enabled()) return;
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);
248 new_pajePopState (SIMIX_get_clock(), container, type);
251 void TRACE_smpi_computing_init(int rank)
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;
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);
267 void TRACE_smpi_computing_in(int rank, instr_extra_data extra)
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);
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);
283 void TRACE_smpi_computing_out(int rank)
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);
293 void TRACE_smpi_sleeping_init(int rank)
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;
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);
309 void TRACE_smpi_sleeping_in(int rank, instr_extra_data extra)
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);
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);
325 void TRACE_smpi_sleeping_out(int rank)
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);
336 void TRACE_smpi_testing_in(int rank, instr_extra_data extra)
338 //do not forget to set the color first, otherwise this will explode
339 if (!TRACE_smpi_is_enabled()) {
340 cleanup_extra_data(extra);
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);
352 void TRACE_smpi_testing_out(int rank)
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);
362 void TRACE_smpi_ptp_in(int rank, int src, int dst, const char *operation, instr_extra_data extra)
364 if (!TRACE_smpi_is_enabled()) {
365 cleanup_extra_data(extra);
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);
378 void TRACE_smpi_ptp_out(int rank, int src, int dst, const char *operation)
380 if (!TRACE_smpi_is_enabled()) return;
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);
387 new_pajePopState (SIMIX_get_clock(), container, type);
390 void TRACE_smpi_send(int rank, int src, int dst, int size)
392 if (!TRACE_smpi_is_enabled()) return;
394 char key[INSTR_DEFAULT_STR_SIZE] = {0};
395 TRACE_smpi_put_key(src, dst, key, INSTR_DEFAULT_STR_SIZE);
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());
402 new_pajeStartLinkWithSize (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key, size);
405 void TRACE_smpi_recv(int rank, int src, int dst)
407 if (!TRACE_smpi_is_enabled()) return;
409 char key[INSTR_DEFAULT_STR_SIZE] = {0};
410 TRACE_smpi_get_key(src, dst, key, INSTR_DEFAULT_STR_SIZE);
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());
417 new_pajeEndLink (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key);
419 #endif /* HAVE_TRACING */