Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[SMPI] Instr: Cleanup TRACE_smpi_init / smpi_container() usage...
[simgrid.git] / src / smpi / internals / instr_smpi.cpp
1 /* Copyright (c) 2010-2018. 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.hpp"
8 #include <boost/algorithm/string.hpp>
9 #include <cctype>
10 #include <cstdarg>
11 #include <cwchar>
12 #include <deque>
13 #include <simgrid/sg_config.hpp>
14 #include <string>
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
17
18 static std::unordered_map<std::string, std::deque<std::string>*> keys;
19
20 static const char* smpi_colors[] = {"recv",
21                                     "1 0 0",
22                                     "irecv",
23                                     "1 0.52 0.52",
24                                     "send",
25                                     "0 0 1",
26                                     "isend",
27                                     "0.52 0.52 1",
28                                     "sendrecv",
29                                     "0 1 1",
30                                     "wait",
31                                     "1 1 0",
32                                     "waitall",
33                                     "0.78 0.78 0",
34                                     "waitany",
35                                     "0.78 0.78 0.58",
36                                     "test",
37                                     "0.52 0.52 0",
38
39                                     "allgather",
40                                     "1 0 0",
41                                     "allgatherv",
42                                     "1 0.52 0.52",
43                                     "allreduce",
44                                     "1 0 1",
45                                     "alltoall",
46                                     "0.52 0 1",
47                                     "alltoallv",
48                                     "0.78 0.52 1",
49                                     "barrier",
50                                     "0 0.78 0.78",
51                                     "bcast",
52                                     "0 0.78 0.39",
53                                     "gather",
54                                     "1 1 0",
55                                     "gatherv",
56                                     "1 1 0.52",
57                                     "reduce",
58                                     "0 1 0",
59                                     "reducescatter",
60                                     "0.52 1 0.52",
61                                     "scan",
62                                     "1 0.58 0.23",
63                                     "exscan",
64                                     "1 0.54 0.25",
65                                     "scatterv",
66                                     "0.52 0 0.52",
67                                     "scatter",
68                                     "1 0.74 0.54",
69
70                                     "computing",
71                                     "0 1 1",
72                                     "sleeping",
73                                     "0 0.5 0.5",
74
75                                     "init",
76                                     "0 1 0",
77                                     "finalize",
78                                     "0 1 0",
79
80                                     "put",
81                                     "0.3 1 0",
82                                     "get",
83                                     "0 1 0.3",
84                                     "accumulate",
85                                     "1 0.3 0",
86                                     "rput",
87                                     "0.3 1 0",
88                                     "rget",
89                                     "0 1 0.3",
90                                     "raccumulate",
91                                     "1 0.3 0",
92                                     "compare_and_swap",
93                                     "0.3 1 0",
94                                     "get_accumulate",
95                                     "0 1 0.3",
96                                     "rget_accumulate",
97                                     "1 0.3 0",
98                                     "win_fence",
99                                     "1 0 0.3",
100                                     "win_post",
101                                     "1 0 0.8",
102                                     "win_wait",
103                                     "1 0.8 0",
104                                     "win_start",
105                                     "0.8 0 1",
106                                     "win_complete",
107                                     "0.8 1 0",
108                                     "win_lock",
109                                     "1 0 0.3",
110                                     "win_unlock",
111                                     "1 0 0.3",
112                                     "win_lock_all",
113                                     "1 0 0.8",
114                                     "win_unlock_all",
115                                     "1 0.8 0",
116                                     "win_flush",
117                                     "1 0 0.3",
118                                     "win_flush_local",
119                                     "1 0 0.8",
120                                     "win_flush_all",
121                                     "1 0.8 0",
122                                     "win_flush_local_all",
123                                     "1 0 0.3",
124                                     "",
125                                     ""};
126
127 static const char* instr_find_color(const char* state)
128 {
129   std::string target = std::string(state);
130   boost::algorithm::to_lower(target);
131   const char* ret     = nullptr;
132   unsigned int i      = 0;
133   const char* current = smpi_colors[i];
134   while (current != nullptr) {
135     if (target == current                          // exact match
136         || strstr(target.c_str(), current) != 0) { // as substring
137       ret = smpi_colors[i + 1];
138       break;
139     }
140     i+=2;
141     current = smpi_colors[i];
142   }
143   return ret;
144 }
145
146 XBT_PRIVATE std::string smpi_container_key(int rank)
147 {
148   return std::string("rank-") + std::to_string(rank);
149 }
150
151 XBT_PRIVATE container_t smpi_container(int rank)
152 {
153   return simgrid::instr::Container::byName(smpi_container_key(rank));
154 }
155
156 static std::string TRACE_smpi_put_key(int src, int dst, int tag, int send)
157 {
158   // get the deque for src#dst
159   std::string aux =
160       std::to_string(src) + "#" + std::to_string(dst) + "#" + std::to_string(tag) + "#" + std::to_string(send);
161   auto it = keys.find(aux);
162   std::deque<std::string>* d;
163
164   if (it == keys.end()) {
165     d         = new std::deque<std::string>;
166     keys[aux] = d;
167   } else
168     d = it->second;
169
170   //generate the key
171   static unsigned long long counter = 0;
172   counter++;
173   std::string key =
174       std::to_string(src) + "_" + std::to_string(dst) + "_" + std::to_string(tag) + "_" + std::to_string(counter);
175
176   //push it
177   d->push_back(key);
178
179   return key;
180 }
181
182 static std::string TRACE_smpi_get_key(int src, int dst, int tag, int send)
183 {
184   std::string key;
185   std::string aux = std::to_string(src) + "#" + std::to_string(dst) + "#" + std::to_string(tag) + "#" +
186                     std::to_string(send == 1 ? 0 : 1);
187   auto it = keys.find(aux);
188   if (it == keys.end()) {
189     // first posted
190     key = TRACE_smpi_put_key(src, dst, tag, send);
191   } else {
192     key = it->second->front();
193     it->second->pop_front();
194   }
195   return key;
196 }
197
198 static std::unordered_map<smx_actor_t, std::string> process_category;
199
200 void TRACE_internal_smpi_set_category (const char *category)
201 {
202   if (not TRACE_smpi_is_enabled())
203     return;
204
205   //declare category
206   TRACE_category (category);
207
208   if (category != nullptr)
209     process_category[SIMIX_process_self()] = category;
210 }
211
212 const char *TRACE_internal_smpi_get_category ()
213 {
214   if (not TRACE_smpi_is_enabled())
215     return nullptr;
216
217   auto it = process_category.find(SIMIX_process_self());
218   return (it == process_category.end()) ? nullptr : it->second.c_str();
219 }
220
221 void TRACE_smpi_release()
222 {
223   for (auto const& elm : keys)
224     delete elm.second;
225 }
226
227 void TRACE_smpi_setup_container(int rank, sg_host_t host)
228 {
229   std::string str = smpi_container_key(rank);
230
231   container_t father;
232   if (TRACE_smpi_is_grouped()){
233     father = simgrid::instr::Container::byNameOrNull(host->get_name());
234   }else{
235     father = simgrid::instr::Container::getRoot();
236   }
237   xbt_assert(father != nullptr, "Could not find a parent for mpi rank %s at function %s", str.c_str(), __func__);
238   father->createChild(str, "MPI"); // This container is of type MPI
239 }
240
241 void TRACE_smpi_init(int rank)
242 {
243   if (not TRACE_smpi_is_enabled())
244     return;
245
246   TRACE_smpi_setup_container(rank, sg_host_self());
247 #if HAVE_PAPI
248   container_t container   = simgrid::instr::Container::byName(str);
249   papi_counter_t counters = smpi_process()->papi_counters();
250
251   for (auto const& it : counters) {
252     /**
253      * Check whether this variable already exists or not. Otherwise, it will be created
254      * multiple times but only the last one would be used...
255      */
256     if (s_type::getOrNull(it.first.c_str(), container->type_) == nullptr) {
257       Type::variableNew(it.first.c_str(), "", container->type_);
258     }
259   }
260 #endif
261 }
262
263 void TRACE_smpi_finalize(int rank)
264 {
265   if (not TRACE_smpi_is_enabled())
266     return;
267
268   smpi_container(rank)->removeFromParent();
269 }
270
271 void TRACE_smpi_computing_init(int rank)
272 {
273  //first use, initialize the color in the trace
274  if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
275    smpi_container(rank)->getState("MPI_STATE")->addEntityValue("computing", instr_find_color("computing"));
276 }
277
278 void TRACE_smpi_computing_in(int rank, double amount)
279 {
280   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
281     smpi_container(rank)
282         ->getState("MPI_STATE")
283         ->pushEvent("computing", new simgrid::instr::CpuTIData("compute", amount));
284 }
285
286 void TRACE_smpi_computing_out(int rank)
287 {
288   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
289     smpi_container(rank)->getState("MPI_STATE")->popEvent();
290 }
291
292 void TRACE_smpi_sleeping_in(int rank, double duration)
293 {
294   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_sleeping())
295     smpi_container(rank)
296         ->getState("MPI_STATE")
297         ->pushEvent("sleeping", new simgrid::instr::CpuTIData("sleep", duration));
298 }
299
300 void TRACE_smpi_sleeping_out(int rank)
301 {
302   if (TRACE_smpi_is_enabled() && not TRACE_smpi_is_sleeping())
303     smpi_container(rank)->getState("MPI_STATE")->popEvent();
304 }
305
306 void TRACE_smpi_testing_in(int rank)
307 {
308   //do not forget to set the color first, otherwise this will explode
309   if (not TRACE_smpi_is_enabled())
310     return;
311
312   simgrid::instr::StateType* state = smpi_container(rank)->getState("MPI_STATE");
313   state->addEntityValue("test");
314   state->pushEvent("test", new simgrid::instr::NoOpTIData("test"));
315 }
316
317 void TRACE_smpi_testing_out(int rank)
318 {
319   if (TRACE_smpi_is_enabled())
320     smpi_container(rank)->getState("MPI_STATE")->popEvent();
321 }
322
323 void TRACE_smpi_comm_in(int rank, const char* operation, simgrid::instr::TIData* extra)
324 {
325   if (not TRACE_smpi_is_enabled()) {
326     delete extra;
327     return;
328   }
329
330   simgrid::instr::StateType* state = smpi_container(rank)->getState("MPI_STATE");
331   state->addEntityValue(operation, instr_find_color(operation));
332   state->pushEvent(operation, extra);
333 }
334
335 void TRACE_smpi_comm_out(int rank)
336 {
337   if (TRACE_smpi_is_enabled())
338     smpi_container(rank)->getState("MPI_STATE")->popEvent();
339 }
340
341 void TRACE_smpi_send(int rank, int src, int dst, int tag, int size)
342 {
343   if (not TRACE_smpi_is_enabled())
344     return;
345
346   std::string key = TRACE_smpi_get_key(src, dst, tag, 1);
347
348   XBT_DEBUG("Send tracing from %d to %d, tag %d, with key %s", src, dst, tag, key.c_str());
349   simgrid::instr::Container::getRoot()->getLink("MPI_LINK")->startEvent(smpi_container(rank), "PTP", key, size);
350 }
351
352 void TRACE_smpi_recv(int src, int dst, int tag)
353 {
354   if (not TRACE_smpi_is_enabled())
355     return;
356
357   std::string key = TRACE_smpi_get_key(src, dst, tag, 0);
358
359   XBT_DEBUG("Recv tracing from %d to %d, tag %d, with key %s", src, dst, tag, key.c_str());
360   simgrid::instr::Container::getRoot()->getLink("MPI_LINK")->endEvent(smpi_container(dst), "PTP", key);
361 }