GCC Code Coverage Report


Directory: ./
File: Core/chrono.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 15 176 8.5%
Branches: 6 452 1.3%

Line Branch Exec Source
1 // ______ ______ _ _ _____ ______
2 // | ____| ____| | (_)/ ____| | ____|
3 // | |__ | |__ | | _| (___ ___| |__
4 // | __| | __| | | | |\___ \ / __| __|
5 // | | | |____| |____| |____) | (__| |____
6 // |_| |______|______|_|_____/ \___|______|
7 // Finite Elements for Life Sciences and Engineering
8 //
9 // License: LGL2.1 License
10 // FELiScE default license: LICENSE in root folder
11 //
12 // Main authors: Vicente Mataix Ferrandiz
13 //
14
15 // System includes
16
17 // External includes
18
19 // Project includes
20 #include "Core/chrono.hpp"
21
22 namespace felisce
23 {
24
25 490 Chrono::Chrono(const bool active):
26 490 m_active(active),
27
1/2
✓ Branch 1 taken 490 times.
✗ Branch 2 not taken.
490 m_resultDir("."),
28
2/4
✓ Branch 3 taken 490 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 490 times.
✗ Branch 7 not taken.
980 m_comm(MPI_COMM_WORLD)
29 {
30 490 m_globalChrono.start();
31 490 }
32
33 /***********************************************************************************/
34 /***********************************************************************************/
35
36 Chrono::Chrono(const bool active, const std::string resultDir, MPI_Comm comm):
37 m_active(active),
38 m_resultDir(resultDir),
39 m_comm(comm)
40 {
41 m_globalChrono.start();
42 }
43
44 /***********************************************************************************/
45 /***********************************************************************************/
46
47 1 void Chrono::Sleep(const int TimeToSleep)
48 {
49
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 std::this_thread::sleep_for(std::chrono::seconds(TimeToSleep));
50 1 }
51
52 /***********************************************************************************/
53 /***********************************************************************************/
54
55 88031 void Chrono::Start(
56 const std::string& rLabel,
57 const int SubLabel
58 )
59 {
60
1/2
✓ Branch 0 taken 88031 times.
✗ Branch 1 not taken.
88031 if ( !m_active )
61 88031 return;
62
63 auto find_label_it = m_chrono.find(rLabel);
64 if (find_label_it == m_chrono.end()) {
65 m_chrono[rLabel] = std::map<int, ChronoInstance>();
66 auto& r_chrono = m_chrono[rLabel];
67 r_chrono[SubLabel] = ChronoInstance();
68 r_chrono[SubLabel].start();
69 } else {
70 auto& r_sub_map = find_label_it->second;
71 auto find_sub_label_it = r_sub_map.find(SubLabel);
72 if (find_sub_label_it == r_sub_map.end())
73 r_sub_map[SubLabel] = ChronoInstance();
74 r_sub_map[SubLabel].start();
75 }
76 }
77
78 /***********************************************************************************/
79 /***********************************************************************************/
80
81 88031 void Chrono::Stop(
82 const std::string& rLabel,
83 const int SubLabel
84 )
85 {
86
1/2
✓ Branch 0 taken 88031 times.
✗ Branch 1 not taken.
88031 if ( !m_active )
87 88031 return;
88
89 auto find_label_it = m_chrono.find(rLabel);
90 if (find_label_it == m_chrono.end()) {
91 std::cerr << "Chrono::Stop: Chrono with name " << rLabel << " not defined. Call Start first" << std::endl;
92 } else {
93 auto& r_sub_map = find_label_it->second;
94 auto find_sub_label_it = r_sub_map.find(SubLabel);
95 if (find_sub_label_it == r_sub_map.end()) {
96 std::cerr << "Chrono::Stop: Chrono with name " << rLabel << " and sublabel " << SubLabel << " not defined. Call Start first" << std::endl;
97 } else {
98 auto& r_chrono = find_sub_label_it->second;
99 r_chrono.stop();
100 }
101 }
102 }
103
104 /***********************************************************************************/
105 /***********************************************************************************/
106
107 double Chrono::Diff(
108 const std::string& rLabel,
109 const int SubLabel
110 )
111 {
112 if ( !m_active )
113 return 0.0;
114
115 auto find_label_it = m_chrono.find(rLabel);
116 if (find_label_it == m_chrono.end()) {
117 std::cerr << "Chrono::Diff: Chrono with name " << rLabel << " not defined. Call Start and Stop first" << std::endl;
118 } else {
119 auto& r_sub_map = find_label_it->second;
120 auto find_sub_label_it = r_sub_map.find(SubLabel);
121 if (find_sub_label_it == r_sub_map.end()) {
122 std::cerr << "Chrono::Diff: Chrono with name " << rLabel << " and sublabel " << SubLabel << " not defined. Call Start and Stop first" << std::endl;
123 } else {
124 auto& r_chrono = find_sub_label_it->second;
125 return r_chrono.diff();
126 }
127 }
128
129 return 0.0;
130 }
131
132 /***********************************************************************************/
133 /***********************************************************************************/
134
135 void Chrono::fillTable()
136 {
137 if ( m_isTableBuilt )
138 return;
139
140 m_isTableBuilt = true;
141
142 // Set percentages
143 const double total_time = getTotalTime();
144
145 // Get the rank of the process
146 int rankProc, numProc;
147 MPI_Comm_rank(m_comm,&rankProc);
148 MPI_Comm_size(m_comm,&numProc);
149
150 m_table.add_row({"Label", "Sublabel", "Time elapsed [CPU"+std::to_string(rankProc)+"] (s)", "Perc. tot. time (%)", "# Calls", "Average time elapsed [CPU"+std::to_string(rankProc)+"] (s)", "Average perc. tot. time (%)"});
151 m_rows += 1;
152
153 // Center-align and color header cells
154 for (std::size_t i = 0; i < 7; ++i) {
155 m_table[0][i].format()
156 .font_color(tabulate::Color::yellow)
157 .font_align(tabulate::FontAlign::center)
158 .font_style({tabulate::FontStyle::bold});
159 }
160
161 for (auto& r_label_chronos: m_chrono) {
162 const auto& r_label_name = r_label_chronos.first;
163 const auto& r_sub_chronos = r_label_chronos.second;
164
165 for (auto& r_sub_label_chrono: r_sub_chronos) {
166 const auto& r_sub_name = r_sub_label_chrono.first;
167 const auto& r_sub_chrono = r_sub_label_chrono.second;
168
169 // Fill the table
170 const double diff = r_sub_chrono.diff_cumul();
171 const double percentage = diff / total_time * 100;
172 std::stringstream buffer;
173 buffer << std::setprecision(16) << std::scientific << diff;
174
175 const uint64_t num = r_sub_chrono.num_call();
176 const double ave_diff = diff / num;
177 const double ave_perc = ave_diff / total_time * 100;
178 std::stringstream buffer_ave;
179 buffer_ave << std::setprecision(16) << std::scientific << ave_diff;
180
181 m_table.add_row({r_label_name, std::to_string(r_sub_name), buffer.str(), std::to_string(percentage), std::to_string(num), buffer_ave.str(), std::to_string(ave_perc) });
182 m_table[m_rows][0].format()
183 .font_color(tabulate::Color::magenta)
184 .font_align(tabulate::FontAlign::left)
185 .font_style({tabulate::FontStyle::bold});
186 m_rows += 1;
187 }
188 }
189
190 // Center align
191 m_table.column(0).format().font_align(tabulate::FontAlign::left);
192 for (std::size_t i = 1; i < 7; ++i) {
193 m_table.column(i).format().font_align(tabulate::FontAlign::center);
194 }
195 }
196
197 /***********************************************************************************/
198 /***********************************************************************************/
199
200 void Chrono::ToScreen()
201 {
202 // Get the rank of the process
203 int rankProc, numProc;
204 MPI_Comm_rank(m_comm,&rankProc);
205 MPI_Comm_size(m_comm,&numProc);
206
207 // Build table
208 fillTable();
209
210 // Print to screen
211 for (int i = 0; i < numProc; ++i) {
212
213 MPI_Barrier(MPI_COMM_WORLD);
214
215 if ( rankProc == i )
216 std::cout << "\n\n" << m_table << "\n\n" << generateGlobalTable() << std::endl;
217
218 MPI_Barrier(MPI_COMM_WORLD);
219 }
220 }
221
222 /***********************************************************************************/
223 /***********************************************************************************/
224
225 void Chrono::ToFile()
226 {
227 // Get the rank of the process
228 int rankProc, numProc;
229 MPI_Comm_rank(m_comm,&rankProc);
230 MPI_Comm_size(m_comm,&numProc);
231
232 // Build table
233 fillTable();
234
235 /* Writes table into file */
236 for (int i = 0; i < numProc; ++i) {
237
238 if ( rankProc == i ) {
239 std::ostringstream filename;
240 filename << m_resultDir << "/" << "chrono" << std::to_string(rankProc) << ".md";
241 std::ofstream f;
242 f.open(filename.str().c_str());
243
244 if ( f.good() ) {
245 // Exported Markdown
246 tabulate::MarkdownExporter exporter_md;
247 auto markdown = exporter_md.dump(m_table);
248 f << markdown << std::endl;
249 f.close();
250 } else {
251 std::ostringstream msg;
252 msg << "Can not write in file " << filename.str() << std::endl;
253 FEL_WARNING(msg.str().c_str());
254 }
255 }
256 }
257
258 /* Writes table into file */
259 for (int i = 0; i < numProc; ++i) {
260
261 if ( rankProc == i ) {
262 std::ostringstream filename;
263 filename << m_resultDir << "/" << "chrono_total" << std::to_string(rankProc) << ".md";
264 std::ofstream f;
265 f.open(filename.str().c_str());
266
267 if ( f.good() ) {
268 // Exported Markdown
269 tabulate::MarkdownExporter exporter_md;
270 auto total_table = generateGlobalTable();
271 auto markdown = exporter_md.dump(total_table);
272 f << markdown << std::endl;
273 f.close();
274 } else {
275 std::ostringstream msg;
276 msg << "Can not write in file " << filename.str() << std::endl;
277 FEL_WARNING(msg.str().c_str());
278 }
279 }
280 }
281 }
282
283 /***********************************************************************************/
284 /***********************************************************************************/
285
286 void Chrono::print(int verbose,std::ostream& c) const
287 {
288 if(verbose) {
289 c << m_table << std::endl;
290 }
291 }
292
293 /***********************************************************************************/
294 /***********************************************************************************/
295
296 tabulate::Table Chrono::generateGlobalTable()
297 {
298 tabulate::Table global_table;
299
300 // Get the total time
301 const double total_time = getTotalTime();
302 double remaining_time = total_time;
303 const std::string total_time_string = std::to_string(total_time);
304
305 // Get the rank of the process
306 int rankProc, numProc;
307 MPI_Comm_rank(m_comm,&rankProc);
308 MPI_Comm_size(m_comm,&numProc);
309
310 global_table.add_row({"Label", "Time elapsed [CPU"+std::to_string(rankProc)+"] (s)", "T. time elapsed [CPU"+std::to_string(rankProc)+"] (s)", "Perc. tot. time (%)"});
311
312 // Center-align and color header cells
313 for (std::size_t i = 0; i < 4; ++i) {
314 global_table[0][i].format()
315 .font_color(tabulate::Color::yellow)
316 .font_align(tabulate::FontAlign::center)
317 .font_style({tabulate::FontStyle::bold});
318 }
319
320 // Add rows
321 std::size_t i = 1;
322 double total_time_label = 0.0;
323 for (auto& r_label_chronos: m_chrono) {
324 total_time_label = 0.0;
325 const auto& r_label_name = r_label_chronos.first;
326 const auto& r_sub_chronos = r_label_chronos.second;
327 for (auto& r_sub_label_chrono: r_sub_chronos) {
328 total_time_label += (r_sub_label_chrono.second).diff_cumul();
329 }
330 remaining_time -= total_time_label;
331 global_table.add_row({r_label_name, std::to_string(total_time_label), total_time_string, std::to_string((total_time_label/total_time)*100)});
332 global_table[i][0].format()
333 .font_color(tabulate::Color::magenta)
334 .font_align(tabulate::FontAlign::left)
335 .font_style({tabulate::FontStyle::bold});
336 ++i;
337 }
338 // In case remaining time is not null
339 if (remaining_time > 0.0) {
340 global_table.add_row({"Remaining time", std::to_string(remaining_time), total_time_string, std::to_string((remaining_time/total_time)*100)});
341 global_table[i][0].format()
342 .font_color(tabulate::Color::magenta)
343 .font_align(tabulate::FontAlign::left)
344 .font_style({tabulate::FontStyle::bold});
345 }
346
347 // Center align
348 global_table.column(0).format().font_align(tabulate::FontAlign::left);
349 for (std::size_t i = 1; i < 4; ++i) {
350 global_table.column(i).format().font_align(tabulate::FontAlign::center);
351 }
352
353 return global_table;
354 }
355 }
356