1 /* Copyright (c) 2010, 2012-2017. 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. */
10 #include <simgrid/sg_config.h>
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
16 static xbt_dict_t keys;
18 static const char *smpi_colors[] ={
20 "irecv", "1 0.52 0.52",
22 "isend", "0.52 0.52 1",
25 "waitall", "0.78 0.78 0",
26 "waitany", "0.78 0.78 0.58",
27 "test", "0.52 0.52 0",
30 "allgatherv", "1 0.52 0.52",
32 "alltoall", "0.52 0 1",
33 "alltoallv", "0.78 0.52 1",
34 "barrier", "0 0.78 0.78",
35 "bcast", "0 0.78 0.39",
37 "gatherv", "1 1 0.52",
39 "reducescatter", "0.52 1 0.52",
40 "scan", "1 0.58 0.23",
41 "exscan", "1 0.54 0.25",
42 "scatterv", "0.52 0 0.52",
43 "scatter", "1 0.74 0.54",
46 "sleeping", "0 0.5 0.5",
53 "accumulate", "1 0.3 0",
54 "win_fence", "1 0 0.3",
55 "win_post", "1 0 0.8",
56 "win_wait", "1 0.8 0",
57 "win_start", "0.8 0 1",
58 "win_complete", "0.8 1 0",
62 static char *str_tolower (const char *str)
64 char* ret = xbt_strdup(str);
66 for (int i = 0; i < n; i++)
67 ret[i] = tolower (str[i]);
71 static const char *instr_find_color (const char *state)
73 char* target = str_tolower(state);
74 const char* ret = nullptr;
76 const char* current = smpi_colors[i];
77 while (current != nullptr) {
78 if (strcmp (state, current) == 0 //exact match
79 || strstr(target, current) != 0 ){//as substring
80 ret = smpi_colors[i+1];
84 current = smpi_colors[i];
90 XBT_PRIVATE char *smpi_container(int rank, char *container, int n)
92 snprintf(container, n, "rank-%d", rank);
96 static char *TRACE_smpi_get_key(int src, int dst, int tag, char *key, int n, int send);
98 static char *TRACE_smpi_put_key(int src, int dst, int tag, char *key, int n, int send)
100 //get the dynar for src#dst
101 char aux[INSTR_DEFAULT_STR_SIZE];
102 snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d#%d#%d", src, dst, tag, send);
103 xbt_dynar_t d = static_cast<xbt_dynar_t>(xbt_dict_get_or_null(keys, aux));
106 d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
107 xbt_dict_set(keys, aux, d, nullptr);
111 static unsigned long long counter = 0;
113 snprintf(key, n, "%d_%d_%d_%llu", src, dst, tag, counter);
116 char *a = static_cast<char*> (xbt_strdup(key));
117 xbt_dynar_push_as(d, char *, a);
122 static char *TRACE_smpi_get_key(int src, int dst, int tag, char *key, int n, int send)
124 char aux[INSTR_DEFAULT_STR_SIZE];
125 snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d#%d#%d", src, dst, tag, send==1?0:1);
126 xbt_dynar_t d = static_cast<xbt_dynar_t>(xbt_dict_get_or_null(keys, aux));
129 if(xbt_dynar_is_empty(d)){
130 TRACE_smpi_put_key(src, dst, tag, key, n, send);
134 char *s = xbt_dynar_get_as (d, 0, char *);
135 snprintf (key, n, "%s", s);
136 xbt_dynar_remove_at (d, 0, nullptr);
140 static xbt_dict_t process_category;
142 static void cleanup_extra_data (instr_extra_data extra){
144 if(extra->sendcounts!=nullptr)
145 xbt_free(extra->sendcounts);
146 if(extra->recvcounts!=nullptr)
147 xbt_free(extra->recvcounts);
152 void TRACE_internal_smpi_set_category (const char *category)
154 if (not TRACE_smpi_is_enabled())
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 != nullptr)
165 xbt_dict_set (process_category, processid, xbt_strdup(category), nullptr);
168 const char *TRACE_internal_smpi_get_category ()
170 if (not TRACE_smpi_is_enabled())
173 char processid[INSTR_DEFAULT_STR_SIZE];
174 snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
175 return static_cast<char*>(xbt_dict_get_or_null (process_category, processid));
178 void TRACE_smpi_alloc()
180 keys = xbt_dict_new_homogeneous(xbt_dynar_free_voidp);
181 process_category = xbt_dict_new_homogeneous(xbt_free_f);
184 void TRACE_smpi_release()
186 xbt_dict_free(&keys);
187 xbt_dict_free(&process_category);
190 void TRACE_smpi_init(int rank)
192 if (not TRACE_smpi_is_enabled())
195 char str[INSTR_DEFAULT_STR_SIZE];
196 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
199 if (TRACE_smpi_is_grouped()){
200 father = PJ_container_get(sg_host_self_get_name());
202 father = PJ_container_get_root ();
204 xbt_assert(father!=nullptr,
205 "Could not find a parent for mpi rank %s at function %s", str, __FUNCTION__);
207 container_t container =
209 PJ_container_new(str, INSTR_SMPI, father);
211 papi_counter_t counters = smpi_process()->papi_counters();
213 for (auto& it : counters) {
215 * Check whether this variable already exists or not. Otherwise, it will be created
216 * multiple times but only the last one would be used...
218 if (PJ_type_get_or_null(it.first.c_str(), container->type) == nullptr) {
219 PJ_type_variable_new(it.first.c_str(), nullptr, container->type);
225 void TRACE_smpi_finalize(int rank)
227 if (not TRACE_smpi_is_enabled())
230 char str[INSTR_DEFAULT_STR_SIZE];
231 container_t container = PJ_container_get(smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE));
232 PJ_container_remove_from_parent (container);
233 PJ_container_free (container);
236 void TRACE_smpi_collective_in(int rank, const char *operation, instr_extra_data extra)
238 if (not TRACE_smpi_is_enabled()) {
239 cleanup_extra_data(extra);
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 const char *color = instr_find_color (operation);
248 value* val = value::get_or_new(operation, color, type);
249 new PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
252 void TRACE_smpi_collective_out(int rank, const char *operation)
254 if (not TRACE_smpi_is_enabled())
257 char str[INSTR_DEFAULT_STR_SIZE];
258 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
259 container_t container = PJ_container_get (str);
260 type_t type = PJ_type_get ("MPI_STATE", container->type);
262 new PopStateEvent (SIMIX_get_clock(), container, type);
265 void TRACE_smpi_computing_init(int rank)
267 //first use, initialize the color in the trace
268 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_computing())
271 char str[INSTR_DEFAULT_STR_SIZE];
272 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
273 container_t container = PJ_container_get(str);
274 type_t type = PJ_type_get("MPI_STATE", container->type);
275 const char* color = instr_find_color("computing");
276 new PushStateEvent(SIMIX_get_clock(), container, type, value::get_or_new("computing", color, type));
279 void TRACE_smpi_computing_in(int rank, instr_extra_data extra)
281 //do not forget to set the color first, otherwise this will explode
282 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_computing()) {
283 cleanup_extra_data(extra);
287 char str[INSTR_DEFAULT_STR_SIZE];
288 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
289 container_t container = PJ_container_get (str);
290 type_t type = PJ_type_get ("MPI_STATE", container->type);
291 value* val = value::get_or_new("computing", nullptr, type);
292 new PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
295 void TRACE_smpi_computing_out(int rank)
297 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_computing())
299 char str[INSTR_DEFAULT_STR_SIZE];
300 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
301 container_t container = PJ_container_get (str);
302 type_t type = PJ_type_get ("MPI_STATE", container->type);
303 new PopStateEvent (SIMIX_get_clock(), container, type);
306 void TRACE_smpi_sleeping_init(int rank)
308 //first use, initialize the color in the trace
309 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_sleeping())
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 const char *color = instr_find_color ("sleeping");
317 value* val = value::get_or_new("sleeping", color, type);
318 new PushStateEvent(SIMIX_get_clock(), container, type, val);
321 void TRACE_smpi_sleeping_in(int rank, instr_extra_data extra)
323 //do not forget to set the color first, otherwise this will explode
324 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_sleeping()) {
325 cleanup_extra_data(extra);
329 char str[INSTR_DEFAULT_STR_SIZE];
330 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
331 container_t container = PJ_container_get (str);
332 type_t type = PJ_type_get ("MPI_STATE", container->type);
333 value* val = value::get_or_new("sleeping", nullptr, type);
334 new PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
337 void TRACE_smpi_sleeping_out(int rank)
339 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_sleeping())
341 char str[INSTR_DEFAULT_STR_SIZE];
342 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
343 container_t container = PJ_container_get (str);
344 type_t type = PJ_type_get ("MPI_STATE", container->type);
345 new PopStateEvent (SIMIX_get_clock(), container, type);
348 void TRACE_smpi_testing_in(int rank, instr_extra_data extra)
350 //do not forget to set the color first, otherwise this will explode
351 if (not TRACE_smpi_is_enabled()) {
352 cleanup_extra_data(extra);
356 char str[INSTR_DEFAULT_STR_SIZE];
357 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
358 container_t container = PJ_container_get (str);
359 type_t type = PJ_type_get ("MPI_STATE", container->type);
360 value* val = value::get_or_new("test", nullptr, type);
361 new PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
364 void TRACE_smpi_testing_out(int rank)
366 if (not TRACE_smpi_is_enabled())
368 char str[INSTR_DEFAULT_STR_SIZE];
369 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
370 container_t container = PJ_container_get (str);
371 type_t type = PJ_type_get ("MPI_STATE", container->type);
372 new PopStateEvent (SIMIX_get_clock(), container, type);
375 void TRACE_smpi_ptp_in(int rank, const char *operation, instr_extra_data extra)
377 if (not TRACE_smpi_is_enabled()) {
378 cleanup_extra_data(extra);
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 const char *color = instr_find_color (operation);
387 value* val = value::get_or_new(operation, color, type);
388 new PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
391 void TRACE_smpi_ptp_out(int rank, int dst, const char *operation)
393 if (not TRACE_smpi_is_enabled())
396 char str[INSTR_DEFAULT_STR_SIZE];
397 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
398 container_t container = PJ_container_get (str);
399 type_t type = PJ_type_get ("MPI_STATE", container->type);
401 new PopStateEvent (SIMIX_get_clock(), container, type);
404 void TRACE_smpi_send(int rank, int src, int dst, int tag, int size)
406 if (not TRACE_smpi_is_enabled())
409 char key[INSTR_DEFAULT_STR_SIZE] = {0};
410 TRACE_smpi_get_key(src, dst, tag, key, INSTR_DEFAULT_STR_SIZE,1);
412 char str[INSTR_DEFAULT_STR_SIZE];
413 smpi_container(src, 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 XBT_DEBUG("Send tracing from %d to %d, tag %d, with key %s", src, dst, tag, key);
417 new StartLinkEvent (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key, size);
420 void TRACE_smpi_recv(int src, int dst, int tag)
422 if (not TRACE_smpi_is_enabled())
425 char key[INSTR_DEFAULT_STR_SIZE] = {0};
426 TRACE_smpi_get_key(src, dst, tag, key, INSTR_DEFAULT_STR_SIZE,0);
428 char str[INSTR_DEFAULT_STR_SIZE];
429 smpi_container(dst, str, INSTR_DEFAULT_STR_SIZE);
430 container_t container = PJ_container_get (str);
431 type_t type = PJ_type_get ("MPI_LINK", PJ_type_get_root());
432 XBT_DEBUG("Recv tracing from %d to %d, tag %d, with key %s", src, dst, tag, key);
433 new EndLinkEvent (SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key);