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 static char *str_tolower (const char *str)
57 char *ret = xbt_strdup (str);
58 int i, n = strlen (ret);
59 for (i = 0; i < n; i++)
60 ret[i] = tolower (str[i]);
64 static const char *instr_find_color (const char *state)
66 char *target = str_tolower (state);
67 const char *ret = NULL;
70 while ((current = smpi_colors[i])){
71 if (strcmp (state, current) == 0){ ret = smpi_colors[i+1]; break; } //exact match
72 if (strstr(target, current)) { ret = smpi_colors[i+1]; break; }; //as substring
80 static char *smpi_container(int rank, char *container, int n)
82 snprintf(container, n, "rank-%d", rank);
86 static char *TRACE_smpi_get_key(int src, int dst, char *key, int n);
89 static char *TRACE_smpi_put_key(int src, int dst, char *key, int n)
91 //get the dynar for src#dst
92 char aux[INSTR_DEFAULT_STR_SIZE];
93 snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d", src, dst);
94 xbt_dynar_t d = xbt_dict_get_or_null(keys, aux);
97 if(!xbt_dynar_is_empty(d)){
98 //receive was already pushed, perform a get instead
99 TRACE_smpi_get_key(src , dst, key ,n);
104 d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
105 xbt_dict_set(keys, aux, d, NULL);
109 static unsigned long long counter = 0;
111 snprintf(key, n, "%d_%d_%llu", src, dst, counter++);
114 char *a = (char*)xbt_strdup(key);
115 xbt_dynar_push_as(d, char *, a);
120 static char *TRACE_smpi_get_key(int src, int dst, char *key, int n)
122 char aux[INSTR_DEFAULT_STR_SIZE];
123 snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d", src, dst);
124 xbt_dynar_t d = xbt_dict_get_or_null(keys, aux);
126 // xbt_assert(!xbt_dynar_is_empty(d),
127 // "Trying to get a link key (for message reception) that has no corresponding send (%s).", __FUNCTION__);
129 // sometimes the receive may be posted before the send
130 if(xbt_dynar_is_empty(d)){
131 TRACE_smpi_put_key(src, dst, key, n);
135 char *s = xbt_dynar_get_as (d, 0, char *);
136 snprintf (key, n, "%s", s);
137 xbt_dynar_remove_at (d, 0, NULL);
141 static xbt_dict_t process_category;
143 static void cleanup_extra_data (instr_extra_data extra){
145 if(extra->sendcounts!=NULL)
146 xbt_free(extra->sendcounts);
147 if(extra->recvcounts!=NULL)
148 xbt_free(extra->recvcounts);
153 void TRACE_internal_smpi_set_category (const char *category)
155 if (!TRACE_smpi_is_enabled()) return;
158 TRACE_category (category);
160 char processid[INSTR_DEFAULT_STR_SIZE];
161 snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
162 if (xbt_dict_get_or_null (process_category, processid))
163 xbt_dict_remove (process_category, processid);
164 if (category != NULL)
165 xbt_dict_set (process_category, processid, xbt_strdup(category), NULL);
168 const char *TRACE_internal_smpi_get_category (void)
170 if (!TRACE_smpi_is_enabled()) return NULL;
172 char processid[INSTR_DEFAULT_STR_SIZE];
173 snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
174 return xbt_dict_get_or_null (process_category, processid);
177 void TRACE_smpi_alloc()
179 keys = xbt_dict_new_homogeneous(xbt_dynar_free_voidp);
180 process_category = xbt_dict_new_homogeneous(xbt_free);
183 void TRACE_smpi_release(void)
185 xbt_dict_free(&keys);
186 xbt_dict_free(&process_category);
189 void TRACE_smpi_init(int rank)
191 if (!TRACE_smpi_is_enabled()) return;
193 char str[INSTR_DEFAULT_STR_SIZE];
194 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
197 if (TRACE_smpi_is_grouped()){
198 father = PJ_container_get (SIMIX_host_self_get_name());
200 father = PJ_container_get_root ();
202 xbt_assert(father!=NULL,
203 "Could not find a parent for mpi rank %s at function %s", str, __FUNCTION__);
204 PJ_container_new(str, INSTR_SMPI, father);
207 void TRACE_smpi_finalize(int rank)
209 if (!TRACE_smpi_is_enabled()) return;
211 char str[INSTR_DEFAULT_STR_SIZE];
212 container_t container = PJ_container_get(smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE));
213 PJ_container_remove_from_parent (container);
214 PJ_container_free (container);
217 void TRACE_smpi_collective_in(int rank, int root, const char *operation, instr_extra_data extra)
219 if (!TRACE_smpi_is_enabled()) {
220 cleanup_extra_data(extra);
224 char str[INSTR_DEFAULT_STR_SIZE];
225 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
226 container_t container = PJ_container_get (str);
227 type_t type = PJ_type_get ("MPI_STATE", container->type);
228 const char *color = instr_find_color (operation);
229 val_t value = PJ_value_get_or_new (operation, color, type);
230 new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
234 void TRACE_smpi_collective_out(int rank, int root, const char *operation)
236 if (!TRACE_smpi_is_enabled()) return;
238 char str[INSTR_DEFAULT_STR_SIZE];
239 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
240 container_t container = PJ_container_get (str);
241 type_t type = PJ_type_get ("MPI_STATE", container->type);
243 new_pajePopState (SIMIX_get_clock(), container, type);
246 void TRACE_smpi_computing_init(int rank)
248 //first use, initialize the color in the trace
249 //TODO : check with lucas and Pierre how to generalize this approach
250 //to avoid unnecessary access to the color array
251 if (!TRACE_smpi_is_enabled() || !TRACE_smpi_is_computing()) return;
253 char str[INSTR_DEFAULT_STR_SIZE];
254 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
255 container_t container = PJ_container_get (str);
256 type_t type = PJ_type_get ("MPI_STATE", container->type);
257 const char *color = instr_find_color ("computing");
258 val_t value = PJ_value_get_or_new ("computing", color, type);
259 new_pajePushState (SIMIX_get_clock(), container, type, value);
262 void TRACE_smpi_computing_in(int rank, instr_extra_data extra)
264 //do not forget to set the color first, otherwise this will explode
265 if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_computing()) {
266 cleanup_extra_data(extra);
270 char str[INSTR_DEFAULT_STR_SIZE];
271 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
272 container_t container = PJ_container_get (str);
273 type_t type = PJ_type_get ("MPI_STATE", container->type);
274 val_t value = PJ_value_get_or_new ("computing", NULL, type);
275 new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
278 void TRACE_smpi_computing_out(int rank)
280 if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_computing()) return;
281 char str[INSTR_DEFAULT_STR_SIZE];
282 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
283 container_t container = PJ_container_get (str);
284 type_t type = PJ_type_get ("MPI_STATE", container->type);
285 new_pajePopState (SIMIX_get_clock(), container, type);
288 void TRACE_smpi_sleeping_init(int rank)
290 //first use, initialize the color in the trace
291 //TODO : check with lucas and Pierre how to generalize this approach
292 //to avoid unnecessary access to the color array
293 if (!TRACE_smpi_is_enabled() || !TRACE_smpi_is_sleeping()) return;
295 char str[INSTR_DEFAULT_STR_SIZE];
296 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
297 container_t container = PJ_container_get (str);
298 type_t type = PJ_type_get ("MPI_STATE", container->type);
299 const char *color = instr_find_color ("sleeping");
300 val_t value = PJ_value_get_or_new ("sleeping", color, type);
301 new_pajePushState (SIMIX_get_clock(), container, type, value);
304 void TRACE_smpi_sleeping_in(int rank, instr_extra_data extra)
306 //do not forget to set the color first, otherwise this will explode
307 if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_sleeping()) {
308 cleanup_extra_data(extra);
312 char str[INSTR_DEFAULT_STR_SIZE];
313 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
314 container_t container = PJ_container_get (str);
315 type_t type = PJ_type_get ("MPI_STATE", container->type);
316 val_t value = PJ_value_get_or_new ("sleeping", NULL, type);
317 new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
320 void TRACE_smpi_sleeping_out(int rank)
322 if (!TRACE_smpi_is_enabled()|| !TRACE_smpi_is_sleeping()) return;
323 char str[INSTR_DEFAULT_STR_SIZE];
324 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
325 container_t container = PJ_container_get (str);
326 type_t type = PJ_type_get ("MPI_STATE", container->type);
327 new_pajePopState (SIMIX_get_clock(), container, type);
331 void TRACE_smpi_testing_in(int rank, instr_extra_data extra)
333 //do not forget to set the color first, otherwise this will explode
334 if (!TRACE_smpi_is_enabled()) {
335 cleanup_extra_data(extra);
339 char str[INSTR_DEFAULT_STR_SIZE];
340 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
341 container_t container = PJ_container_get (str);
342 type_t type = PJ_type_get ("MPI_STATE", container->type);
343 val_t value = PJ_value_get_or_new ("test", NULL, type);
344 new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
347 void TRACE_smpi_testing_out(int rank)
349 if (!TRACE_smpi_is_enabled()) return;
350 char str[INSTR_DEFAULT_STR_SIZE];
351 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
352 container_t container = PJ_container_get (str);
353 type_t type = PJ_type_get ("MPI_STATE", container->type);
354 new_pajePopState (SIMIX_get_clock(), container, type);
357 void TRACE_smpi_ptp_in(int rank, int src, int dst, const char *operation, instr_extra_data extra)
359 if (!TRACE_smpi_is_enabled()) {
360 cleanup_extra_data(extra);
364 char str[INSTR_DEFAULT_STR_SIZE];
365 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
366 container_t container = PJ_container_get (str);
367 type_t type = PJ_type_get ("MPI_STATE", container->type);
368 const char *color = instr_find_color (operation);
369 val_t value = PJ_value_get_or_new (operation, color, type);
370 new_pajePushStateWithExtra (SIMIX_get_clock(), container, type, value, (void*)extra);
373 void TRACE_smpi_ptp_out(int rank, int src, int dst, const char *operation)
375 if (!TRACE_smpi_is_enabled()) return;
377 char str[INSTR_DEFAULT_STR_SIZE];
378 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
379 container_t container = PJ_container_get (str);
380 type_t type = PJ_type_get ("MPI_STATE", container->type);
382 new_pajePopState (SIMIX_get_clock(), container, type);
385 void TRACE_smpi_send(int rank, int src, int dst, int size)
387 if (!TRACE_smpi_is_enabled()) return;
389 char key[INSTR_DEFAULT_STR_SIZE] = {0};
390 TRACE_smpi_put_key(src, dst, key, INSTR_DEFAULT_STR_SIZE);
392 char str[INSTR_DEFAULT_STR_SIZE];
393 smpi_container(src, str, INSTR_DEFAULT_STR_SIZE);
394 container_t container = PJ_container_get (str);
395 type_t type = PJ_type_get ("MPI_LINK", PJ_type_get_root());
397 new_pajeStartLinkWithSize (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key, size);
400 void TRACE_smpi_recv(int rank, int src, int dst)
402 if (!TRACE_smpi_is_enabled()) return;
404 char key[INSTR_DEFAULT_STR_SIZE] = {0};
405 TRACE_smpi_get_key(src, dst, key, INSTR_DEFAULT_STR_SIZE);
407 char str[INSTR_DEFAULT_STR_SIZE];
408 smpi_container(dst, str, INSTR_DEFAULT_STR_SIZE);
409 container_t container = PJ_container_get (str);
410 type_t type = PJ_type_get ("MPI_LINK", PJ_type_get_root());
412 new_pajeEndLink (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key);
414 #endif /* HAVE_TRACING */