Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update copyright headers.
[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 container_t smpi_container(int rank)
147 {
148   return simgrid::instr::Container::byName(std::string("rank-") + std::to_string(rank));
149 }
150
151 static std::string TRACE_smpi_put_key(int src, int dst, int tag, int send)
152 {
153   // get the deque for src#dst
154   std::string aux =
155       std::to_string(src) + "#" + std::to_string(dst) + "#" + std::to_string(tag) + "#" + std::to_string(send);
156   auto it = keys.find(aux);
157   std::deque<std::string>* d;
158
159   if (it == keys.end()) {
160     d         = new std::deque<std::string>;
161     keys[aux] = d;
162   } else
163     d = it->second;
164
165   //generate the key
166   static unsigned long long counter = 0;
167   counter++;
168   std::string key =
169       std::to_string(src) + "_" + std::to_string(dst) + "_" + std::to_string(tag) + "_" + std::to_string(counter);
170
171   //push it
172   d->push_back(key);
173
174   return key;
175 }
176
177 static std::string TRACE_smpi_get_key(int src, int dst, int tag, int send)
178 {
179   std::string key;
180   std::string aux = std::to_string(src) + "#" + std::to_string(dst) + "#" + std::to_string(tag) + "#" +
181                     std::to_string(send == 1 ? 0 : 1);
182   auto it = keys.find(aux);
183   if (it == keys.end()) {
184     // first posted
185     key = TRACE_smpi_put_key(src, dst, tag, send);
186   } else {
187     key = it->second->front();
188     it->second->pop_front();
189   }
190   return key;
191 }
192
193 static std::unordered_map<smx_actor_t, std::string> process_category;
194
195 void TRACE_internal_smpi_set_category (const char *category)
196 {
197   if (not TRACE_smpi_is_enabled())
198     return;
199
200   //declare category
201   TRACE_category (category);
202
203   if (category != nullptr)
204     process_category[SIMIX_process_self()] = category;
205 }
206
207 const char *TRACE_internal_smpi_get_category ()
208 {
209   if (not TRACE_smpi_is_enabled())
210     return nullptr;
211
212   auto it = process_category.find(SIMIX_process_self());
213   return (it == process_category.end()) ? nullptr : it->second.c_str();
214 }
215
216 void TRACE_smpi_alloc()
217 {
218   // for symmetry
219 }
220
221 void TRACE_smpi_release()
222 {
223   for (auto const& elm : keys)
224     delete elm.second;
225 }
226
227 void TRACE_smpi_init(int rank)
228 {
229   if (not TRACE_smpi_is_enabled())
230     return;
231
232   std::string str = std::string("rank-") + std::to_string(rank);
233
234   container_t father;
235   if (TRACE_smpi_is_grouped()){
236     father = simgrid::instr::Container::byNameOrNull(sg_host_self_get_name());
237   }else{
238     father = simgrid::instr::Container::getRoot();
239   }
240   xbt_assert(father != nullptr, "Could not find a parent for mpi rank %s at function %s", str.c_str(), __func__);
241   father->createChild(str, "MPI");
242 #if HAVE_PAPI
243   container_t container   = simgrid::instr::Container::byName(str);
244   papi_counter_t counters = smpi_process()->papi_counters();
245
246   for (auto const& it : counters) {
247     /**
248      * Check whether this variable already exists or not. Otherwise, it will be created
249      * multiple times but only the last one would be used...
250      */
251     if (s_type::getOrNull(it.first.c_str(), container->type_) == nullptr) {
252       Type::variableNew(it.first.c_str(), "", container->type_);
253     }
254   }
255 #endif
256 }
257
258 void TRACE_smpi_finalize(int rank)
259 {
260   if (not TRACE_smpi_is_enabled())
261     return;
262
263   smpi_container(rank)->removeFromParent();
264 }
265
266 void TRACE_smpi_computing_init(int rank)
267 {
268  //first use, initialize the color in the trace
269  if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
270    smpi_container(rank)->getState("MPI_STATE")->addEntityValue("computing", instr_find_color("computing"));
271 }
272
273 void TRACE_smpi_computing_in(int rank, double amount)
274 {
275   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
276     smpi_container(rank)
277         ->getState("MPI_STATE")
278         ->pushEvent("computing", new simgrid::instr::CpuTIData("compute", amount));
279 }
280
281 void TRACE_smpi_computing_out(int rank)
282 {
283   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
284     smpi_container(rank)->getState("MPI_STATE")->popEvent();
285 }
286
287 void TRACE_smpi_sleeping_in(int rank, double duration)
288 {
289   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_sleeping())
290     smpi_container(rank)
291         ->getState("MPI_STATE")
292         ->pushEvent("sleeping", new simgrid::instr::CpuTIData("sleep", duration));
293 }
294
295 void TRACE_smpi_sleeping_out(int rank)
296 {
297   if (TRACE_smpi_is_enabled() && not TRACE_smpi_is_sleeping())
298     smpi_container(rank)->getState("MPI_STATE")->popEvent();
299 }
300
301 void TRACE_smpi_testing_in(int rank)
302 {
303   //do not forget to set the color first, otherwise this will explode
304   if (not TRACE_smpi_is_enabled())
305     return;
306
307   simgrid::instr::StateType* state = smpi_container(rank)->getState("MPI_STATE");
308   state->addEntityValue("test");
309   state->pushEvent("test", new simgrid::instr::NoOpTIData("test"));
310 }
311
312 void TRACE_smpi_testing_out(int rank)
313 {
314   if (TRACE_smpi_is_enabled())
315     smpi_container(rank)->getState("MPI_STATE")->popEvent();
316 }
317
318 void TRACE_smpi_comm_in(int rank, const char* operation, simgrid::instr::TIData* extra)
319 {
320   if (not TRACE_smpi_is_enabled()) {
321     delete extra;
322     return;
323   }
324
325   simgrid::instr::StateType* state = smpi_container(rank)->getState("MPI_STATE");
326   state->addEntityValue(operation, instr_find_color(operation));
327   state->pushEvent(operation, extra);
328 }
329
330 void TRACE_smpi_comm_out(int rank)
331 {
332   if (TRACE_smpi_is_enabled())
333     smpi_container(rank)->getState("MPI_STATE")->popEvent();
334 }
335
336 void TRACE_smpi_send(int rank, int src, int dst, int tag, int size)
337 {
338   if (not TRACE_smpi_is_enabled())
339     return;
340
341   std::string key = TRACE_smpi_get_key(src, dst, tag, 1);
342
343   XBT_DEBUG("Send tracing from %d to %d, tag %d, with key %s", src, dst, tag, key.c_str());
344   simgrid::instr::Container::getRoot()->getLink("MPI_LINK")->startEvent(smpi_container(rank), "PTP", key, size);
345 }
346
347 void TRACE_smpi_recv(int src, int dst, int tag)
348 {
349   if (not TRACE_smpi_is_enabled())
350     return;
351
352   std::string key = TRACE_smpi_get_key(src, dst, tag, 0);
353
354   XBT_DEBUG("Recv tracing from %d to %d, tag %d, with key %s", src, dst, tag, key.c_str());
355   simgrid::instr::Container::getRoot()->getLink("MPI_LINK")->endEvent(smpi_container(dst), "PTP", key);
356 }