Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
[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 <simgrid/s4u/Actor.hpp>
10 #include <cctype>
11 #include <cstdarg>
12 #include <cwchar>
13 #include <deque>
14 #include <simgrid/sg_config.hpp>
15 #include <simgrid/s4u/Host.hpp>
16 #include <string>
17 #include <vector>
18
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
20
21 static std::unordered_map<std::string, std::deque<std::string>*> keys;
22
23 static const char* smpi_colors[] = {"recv",
24                                     "1 0 0",
25                                     "irecv",
26                                     "1 0.52 0.52",
27                                     "send",
28                                     "0 0 1",
29                                     "isend",
30                                     "0.52 0.52 1",
31                                     "sendrecv",
32                                     "0 1 1",
33                                     "wait",
34                                     "1 1 0",
35                                     "waitall",
36                                     "0.78 0.78 0",
37                                     "waitany",
38                                     "0.78 0.78 0.58",
39                                     "test",
40                                     "0.52 0.52 0",
41
42                                     "allgather",
43                                     "1 0 0",
44                                     "allgatherv",
45                                     "1 0.52 0.52",
46                                     "allreduce",
47                                     "1 0 1",
48                                     "alltoall",
49                                     "0.52 0 1",
50                                     "alltoallv",
51                                     "0.78 0.52 1",
52                                     "barrier",
53                                     "0 0.78 0.78",
54                                     "bcast",
55                                     "0 0.78 0.39",
56                                     "gather",
57                                     "1 1 0",
58                                     "gatherv",
59                                     "1 1 0.52",
60                                     "reduce",
61                                     "0 1 0",
62                                     "reducescatter",
63                                     "0.52 1 0.52",
64                                     "scan",
65                                     "1 0.58 0.23",
66                                     "exscan",
67                                     "1 0.54 0.25",
68                                     "scatterv",
69                                     "0.52 0 0.52",
70                                     "scatter",
71                                     "1 0.74 0.54",
72
73                                     "computing",
74                                     "0 1 1",
75                                     "sleeping",
76                                     "0 0.5 0.5",
77
78                                     "init",
79                                     "0 1 0",
80                                     "finalize",
81                                     "0 1 0",
82
83                                     "put",
84                                     "0.3 1 0",
85                                     "get",
86                                     "0 1 0.3",
87                                     "accumulate",
88                                     "1 0.3 0",
89                                     "migration",
90                                     "0.2 0.5 0.2",
91                                     "rput",
92                                     "0.3 1 0",
93                                     "rget",
94                                     "0 1 0.3",
95                                     "raccumulate",
96                                     "1 0.3 0",
97                                     "compare_and_swap",
98                                     "0.3 1 0",
99                                     "get_accumulate",
100                                     "0 1 0.3",
101                                     "rget_accumulate",
102                                     "1 0.3 0",
103                                     "win_fence",
104                                     "1 0 0.3",
105                                     "win_post",
106                                     "1 0 0.8",
107                                     "win_wait",
108                                     "1 0.8 0",
109                                     "win_start",
110                                     "0.8 0 1",
111                                     "win_complete",
112                                     "0.8 1 0",
113                                     "win_lock",
114                                     "1 0 0.3",
115                                     "win_unlock",
116                                     "1 0 0.3",
117                                     "win_lock_all",
118                                     "1 0 0.8",
119                                     "win_unlock_all",
120                                     "1 0.8 0",
121                                     "win_flush",
122                                     "1 0 0.3",
123                                     "win_flush_local",
124                                     "1 0 0.8",
125                                     "win_flush_all",
126                                     "1 0.8 0",
127                                     "win_flush_local_all",
128                                     "1 0 0.3",
129                                     "",
130                                     ""};
131
132 static const char* instr_find_color(const char* state)
133 {
134   std::string target = std::string(state);
135   boost::algorithm::to_lower(target);
136   const char* ret     = nullptr;
137   unsigned int i      = 0;
138   const char* current = smpi_colors[i];
139   while (current != nullptr) {
140     if (target == current                          // exact match
141         || strstr(target.c_str(), current) != 0) { // as substring
142       ret = smpi_colors[i + 1];
143       break;
144     }
145     i+=2;
146     current = smpi_colors[i];
147   }
148   return ret;
149 }
150
151 XBT_PRIVATE container_t smpi_container(int rank)
152 {
153   return simgrid::instr::Container::by_name(std::string("rank-") + std::to_string(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   container_t father = simgrid::instr::Container::get_root();
230   if (TRACE_smpi_is_grouped()) {
231     father = simgrid::instr::Container::by_name_or_null(host->get_name());
232     xbt_assert(father != nullptr, "Could not find a parent for mpi rank 'rank-%d' at function %s", rank, __func__);
233   }
234   father->create_child(std::string("rank-") + std::to_string(rank), "MPI"); // This container is of type MPI
235 }
236
237 void TRACE_smpi_init(int rank)
238 {
239   if (not TRACE_smpi_is_enabled())
240     return;
241
242   TRACE_smpi_setup_container(rank, sg_host_self());
243 #if HAVE_PAPI
244   container_t container   = simgrid::instr::Container::by_name(str);
245   papi_counter_t counters = smpi_process()->papi_counters();
246
247   for (auto const& it : counters) {
248     /**
249      * Check whether this variable already exists or not. Otherwise, it will be created
250      * multiple times but only the last one would be used...
251      */
252     if (s_type::getOrNull(it.first.c_str(), container->type_) == nullptr) {
253       Type::variableNew(it.first.c_str(), "", container->type_);
254     }
255   }
256 #endif
257 }
258
259 void TRACE_smpi_finalize(int rank)
260 {
261   if (not TRACE_smpi_is_enabled())
262     return;
263
264   smpi_container(rank)->remove_from_parent();
265 }
266
267 void TRACE_smpi_computing_init(int rank)
268 {
269  //first use, initialize the color in the trace
270  if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
271    smpi_container(rank)->get_state("MPI_STATE")->add_entity_value("computing", instr_find_color("computing"));
272 }
273
274 void TRACE_smpi_computing_in(int rank, double amount)
275 {
276   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
277     smpi_container(rank)
278         ->get_state("MPI_STATE")
279         ->push_event("computing", new simgrid::instr::CpuTIData("compute", amount));
280 }
281
282 void TRACE_smpi_computing_out(int rank)
283 {
284   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_computing())
285     smpi_container(rank)->get_state("MPI_STATE")->pop_event();
286 }
287
288 void TRACE_smpi_sleeping_in(int rank, double duration)
289 {
290   if (TRACE_smpi_is_enabled() && TRACE_smpi_is_sleeping())
291     smpi_container(rank)
292         ->get_state("MPI_STATE")
293         ->push_event("sleeping", new simgrid::instr::CpuTIData("sleep", duration));
294 }
295
296 void TRACE_smpi_sleeping_out(int rank)
297 {
298   if (TRACE_smpi_is_enabled() && not TRACE_smpi_is_sleeping())
299     smpi_container(rank)->get_state("MPI_STATE")->pop_event();
300 }
301
302 void TRACE_smpi_testing_in(int rank)
303 {
304   //do not forget to set the color first, otherwise this will explode
305   if (not TRACE_smpi_is_enabled())
306     return;
307
308   simgrid::instr::StateType* state = smpi_container(rank)->get_state("MPI_STATE");
309   state->add_entity_value("test");
310   state->push_event("test", new simgrid::instr::NoOpTIData("test"));
311 }
312
313 void TRACE_smpi_testing_out(int rank)
314 {
315   if (TRACE_smpi_is_enabled())
316     smpi_container(rank)->get_state("MPI_STATE")->pop_event();
317 }
318
319 void TRACE_smpi_comm_in(int rank, const char* operation, simgrid::instr::TIData* extra)
320 {
321   if (not TRACE_smpi_is_enabled()) {
322     delete extra;
323     return;
324   }
325
326   simgrid::instr::StateType* state = smpi_container(rank)->get_state("MPI_STATE");
327   state->add_entity_value(operation, instr_find_color(operation));
328   state->push_event(operation, extra);
329 }
330
331 void TRACE_smpi_comm_out(int rank)
332 {
333   if (TRACE_smpi_is_enabled())
334     smpi_container(rank)->get_state("MPI_STATE")->pop_event();
335 }
336
337 void TRACE_smpi_send(int rank, int src, int dst, int tag, int size)
338 {
339   if (not TRACE_smpi_is_enabled())
340     return;
341
342   std::string key = TRACE_smpi_get_key(src, dst, tag, 1);
343
344   XBT_DEBUG("Send tracing from %d to %d, tag %d, with key %s", src, dst, tag, key.c_str());
345   simgrid::instr::Container::get_root()->get_link("MPI_LINK")->start_event(smpi_container(rank), "PTP", key, size);
346 }
347
348 void TRACE_smpi_recv(int src, int dst, int tag)
349 {
350   if (not TRACE_smpi_is_enabled())
351     return;
352
353   std::string key = TRACE_smpi_get_key(src, dst, tag, 0);
354
355   XBT_DEBUG("Recv tracing from %d to %d, tag %d, with key %s", src, dst, tag, key.c_str());
356   simgrid::instr::Container::get_root()->get_link("MPI_LINK")->end_event(smpi_container(dst), "PTP", key);
357 }
358
359 /**************** Functions to trace the migration of tasks. *****************/
360 void TRACE_smpi_send_process_data_in(int rank)
361 {
362   if (!TRACE_smpi_is_enabled()) return;
363
364   smpi_container(rank)->get_state("MIGRATE_STATE")->add_entity_value("migration", instr_find_color("migration"));
365   smpi_container(rank)->get_state("MIGRATE_STATE")->push_event("migration");
366 }
367
368 void TRACE_smpi_send_process_data_out(int rank)
369 {
370   if (!TRACE_smpi_is_enabled()) return; 
371
372   /* Clean the process state. */
373   smpi_container(rank)->get_state("MIGRATE_STATE")->pop_event();
374 }
375
376 void TRACE_smpi_process_change_host(int rank, sg_host_t new_host)
377 {
378   if (!TRACE_smpi_is_enabled()) return;
379
380   /** The key is (most likely) used to match the events in the trace */
381   static long long int counter = 0;
382   std::string key              = std::to_string(counter);
383   counter++;
384
385   // start link (= tell the trace that this rank moves from A to B)
386   container_t cont = smpi_container(rank);
387   simgrid::instr::Container::get_root()->get_link("MIGRATE_LINK")->start_event(cont, "M", key);
388
389   // Destroy container of this rank on this host
390   cont->remove_from_parent();
391
392   // Setup container on new host
393   TRACE_smpi_setup_container(rank, new_host);
394
395   // end link
396   cont = smpi_container(rank); // This points to the newly created container
397   simgrid::instr::Container::get_root()->get_link("MIGRATE_LINK")->end_event(cont, "M", key);
398 }