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. */
13 #include <simgrid/sg_config.h>
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
17 static std::unordered_map<char*, std::deque<std::string>*> keys;
19 static const char *smpi_colors[] ={
21 "irecv", "1 0.52 0.52",
23 "isend", "0.52 0.52 1",
26 "waitall", "0.78 0.78 0",
27 "waitany", "0.78 0.78 0.58",
28 "test", "0.52 0.52 0",
31 "allgatherv", "1 0.52 0.52",
33 "alltoall", "0.52 0 1",
34 "alltoallv", "0.78 0.52 1",
35 "barrier", "0 0.78 0.78",
36 "bcast", "0 0.78 0.39",
38 "gatherv", "1 1 0.52",
40 "reducescatter", "0.52 1 0.52",
41 "scan", "1 0.58 0.23",
42 "exscan", "1 0.54 0.25",
43 "scatterv", "0.52 0 0.52",
44 "scatter", "1 0.74 0.54",
47 "sleeping", "0 0.5 0.5",
54 "accumulate", "1 0.3 0",
55 "win_fence", "1 0 0.3",
56 "win_post", "1 0 0.8",
57 "win_wait", "1 0.8 0",
58 "win_start", "0.8 0 1",
59 "win_complete", "0.8 1 0",
63 static char *str_tolower (const char *str)
65 char* ret = xbt_strdup(str);
67 for (int i = 0; i < n; i++)
68 ret[i] = tolower (str[i]);
72 static const char *instr_find_color (const char *state)
74 char* target = str_tolower(state);
75 const char* ret = nullptr;
77 const char* current = smpi_colors[i];
78 while (current != nullptr) {
79 if (strcmp (state, current) == 0 //exact match
80 || strstr(target, current) != 0 ){//as substring
81 ret = smpi_colors[i+1];
85 current = smpi_colors[i];
91 XBT_PRIVATE char *smpi_container(int rank, char *container, int n)
93 snprintf(container, n, "rank-%d", rank);
97 static char *TRACE_smpi_get_key(int src, int dst, int tag, char *key, int n, int send);
99 static char *TRACE_smpi_put_key(int src, int dst, int tag, char *key, int n, int send)
101 //get the dynar for src#dst
102 char aux[INSTR_DEFAULT_STR_SIZE];
103 snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d#%d#%d", src, dst, tag, send);
104 auto it = keys.find(aux);
105 std::deque<std::string>* d;
107 if (it == keys.end()) {
108 d = new std::deque<std::string>;
114 static unsigned long long counter = 0;
116 snprintf(key, n, "%d_%d_%d_%llu", src, dst, tag, counter);
124 static char *TRACE_smpi_get_key(int src, int dst, int tag, char *key, int n, int send)
126 char aux[INSTR_DEFAULT_STR_SIZE];
127 snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d#%d#%d", src, dst, tag, send==1?0:1);
128 auto it = keys.find(aux);
129 if (it == keys.end()) {
131 TRACE_smpi_put_key(src, dst, tag, key, n, send);
133 snprintf(key, n, "%s", it->second->front().c_str());
134 it->second->pop_front();
139 static std::unordered_map<smx_actor_t, std::string> process_category;
141 static void cleanup_extra_data (instr_extra_data extra){
143 if(extra->sendcounts!=nullptr)
144 xbt_free(extra->sendcounts);
145 if(extra->recvcounts!=nullptr)
146 xbt_free(extra->recvcounts);
151 void TRACE_internal_smpi_set_category (const char *category)
153 if (not TRACE_smpi_is_enabled())
157 TRACE_category (category);
159 if (category != nullptr)
160 process_category[SIMIX_process_self()] = category;
163 const char *TRACE_internal_smpi_get_category ()
165 if (not TRACE_smpi_is_enabled())
168 auto it = process_category.find(SIMIX_process_self());
169 return (it == process_category.end()) ? nullptr : it->second.c_str();
172 void TRACE_smpi_alloc()
177 void TRACE_smpi_release()
179 for (auto const& elm : keys)
183 void TRACE_smpi_init(int rank)
185 if (not TRACE_smpi_is_enabled())
188 char str[INSTR_DEFAULT_STR_SIZE];
189 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
192 if (TRACE_smpi_is_grouped()){
193 father = PJ_container_get(sg_host_self_get_name());
195 father = PJ_container_get_root ();
197 xbt_assert(father!=nullptr,
198 "Could not find a parent for mpi rank %s at function %s", str, __FUNCTION__);
200 container_t container =
202 PJ_container_new(str, simgrid::instr::INSTR_SMPI, father);
204 papi_counter_t counters = smpi_process()->papi_counters();
206 for (auto const& it : counters) {
208 * Check whether this variable already exists or not. Otherwise, it will be created
209 * multiple times but only the last one would be used...
211 if (s_type::getOrNull(it.first.c_str(), container->type_) == nullptr) {
212 Type::variableNew(it.first.c_str(), nullptr, container->type_);
218 void TRACE_smpi_finalize(int rank)
220 if (not TRACE_smpi_is_enabled())
223 char str[INSTR_DEFAULT_STR_SIZE];
224 container_t container = PJ_container_get(smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE));
225 PJ_container_remove_from_parent (container);
226 PJ_container_free (container);
229 void TRACE_smpi_collective_in(int rank, const char *operation, instr_extra_data extra)
231 if (not TRACE_smpi_is_enabled()) {
232 cleanup_extra_data(extra);
236 char str[INSTR_DEFAULT_STR_SIZE];
237 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
238 container_t container = PJ_container_get (str);
239 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
240 const char *color = instr_find_color (operation);
241 simgrid::instr::Value* val = simgrid::instr::Value::get_or_new(operation, color, type);
242 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
245 void TRACE_smpi_collective_out(int rank, const char *operation)
247 if (not TRACE_smpi_is_enabled())
250 char str[INSTR_DEFAULT_STR_SIZE];
251 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
252 container_t container = PJ_container_get (str);
253 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
255 new simgrid::instr::PopStateEvent(SIMIX_get_clock(), container, type);
258 void TRACE_smpi_computing_init(int rank)
260 //first use, initialize the color in the trace
261 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_computing())
264 char str[INSTR_DEFAULT_STR_SIZE];
265 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
266 container_t container = PJ_container_get(str);
267 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
268 const char* color = instr_find_color("computing");
269 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type,
270 simgrid::instr::Value::get_or_new("computing", color, type));
273 void TRACE_smpi_computing_in(int rank, instr_extra_data extra)
275 //do not forget to set the color first, otherwise this will explode
276 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_computing()) {
277 cleanup_extra_data(extra);
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 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
285 simgrid::instr::Value* val = simgrid::instr::Value::get_or_new("computing", nullptr, type);
286 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
289 void TRACE_smpi_computing_out(int rank)
291 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_computing())
293 char str[INSTR_DEFAULT_STR_SIZE];
294 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
295 container_t container = PJ_container_get (str);
296 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
297 new simgrid::instr::PopStateEvent(SIMIX_get_clock(), container, type);
300 void TRACE_smpi_sleeping_init(int rank)
302 //first use, initialize the color in the trace
303 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_sleeping())
306 char str[INSTR_DEFAULT_STR_SIZE];
307 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
308 container_t container = PJ_container_get (str);
309 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
310 const char *color = instr_find_color ("sleeping");
311 simgrid::instr::Value* val = simgrid::instr::Value::get_or_new("sleeping", color, type);
312 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type, val);
315 void TRACE_smpi_sleeping_in(int rank, instr_extra_data extra)
317 //do not forget to set the color first, otherwise this will explode
318 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_sleeping()) {
319 cleanup_extra_data(extra);
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 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
327 simgrid::instr::Value* val = simgrid::instr::Value::get_or_new("sleeping", nullptr, type);
328 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
331 void TRACE_smpi_sleeping_out(int rank)
333 if (not TRACE_smpi_is_enabled() || not TRACE_smpi_is_sleeping())
335 char str[INSTR_DEFAULT_STR_SIZE];
336 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
337 container_t container = PJ_container_get (str);
338 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
339 new simgrid::instr::PopStateEvent(SIMIX_get_clock(), container, type);
342 void TRACE_smpi_testing_in(int rank, instr_extra_data extra)
344 //do not forget to set the color first, otherwise this will explode
345 if (not TRACE_smpi_is_enabled()) {
346 cleanup_extra_data(extra);
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 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
354 simgrid::instr::Value* val = simgrid::instr::Value::get_or_new("test", nullptr, type);
355 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
358 void TRACE_smpi_testing_out(int rank)
360 if (not TRACE_smpi_is_enabled())
362 char str[INSTR_DEFAULT_STR_SIZE];
363 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
364 container_t container = PJ_container_get (str);
365 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
366 new simgrid::instr::PopStateEvent(SIMIX_get_clock(), container, type);
369 void TRACE_smpi_ptp_in(int rank, const char *operation, instr_extra_data extra)
371 if (not TRACE_smpi_is_enabled()) {
372 cleanup_extra_data(extra);
376 char str[INSTR_DEFAULT_STR_SIZE];
377 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
378 container_t container = PJ_container_get (str);
379 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
380 const char *color = instr_find_color (operation);
381 simgrid::instr::Value* val = simgrid::instr::Value::get_or_new(operation, color, type);
382 new simgrid::instr::PushStateEvent(SIMIX_get_clock(), container, type, val, static_cast<void*>(extra));
385 void TRACE_smpi_ptp_out(int rank, int dst, const char *operation)
387 if (not TRACE_smpi_is_enabled())
390 char str[INSTR_DEFAULT_STR_SIZE];
391 smpi_container(rank, str, INSTR_DEFAULT_STR_SIZE);
392 container_t container = PJ_container_get (str);
393 simgrid::instr::Type* type = PJ_type_get("MPI_STATE", container->type_);
395 new simgrid::instr::PopStateEvent(SIMIX_get_clock(), container, type);
398 void TRACE_smpi_send(int rank, int src, int dst, int tag, int size)
400 if (not TRACE_smpi_is_enabled())
403 char key[INSTR_DEFAULT_STR_SIZE] = {0};
404 TRACE_smpi_get_key(src, dst, tag, key, INSTR_DEFAULT_STR_SIZE,1);
406 char str[INSTR_DEFAULT_STR_SIZE];
407 smpi_container(src, str, INSTR_DEFAULT_STR_SIZE);
408 container_t container = PJ_container_get (str);
409 simgrid::instr::Type* type = PJ_type_get("MPI_LINK", PJ_type_get_root());
410 XBT_DEBUG("Send tracing from %d to %d, tag %d, with key %s", src, dst, tag, key);
411 new simgrid::instr::StartLinkEvent(SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key, size);
414 void TRACE_smpi_recv(int src, int dst, int tag)
416 if (not TRACE_smpi_is_enabled())
419 char key[INSTR_DEFAULT_STR_SIZE] = {0};
420 TRACE_smpi_get_key(src, dst, tag, key, INSTR_DEFAULT_STR_SIZE,0);
422 char str[INSTR_DEFAULT_STR_SIZE];
423 smpi_container(dst, str, INSTR_DEFAULT_STR_SIZE);
424 container_t container = PJ_container_get (str);
425 simgrid::instr::Type* type = PJ_type_get("MPI_LINK", PJ_type_get_root());
426 XBT_DEBUG("Recv tracing from %d to %d, tag %d, with key %s", src, dst, tag, key);
427 new simgrid::instr::EndLinkEvent(SIMIX_get_clock(), PJ_container_get_root(), type, container, "PTP", key);