ExaDG
Loading...
Searching...
No Matches
print_solver_results.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef INCLUDE_EXADG_UTILITIES_PRINT_SOLVER_RESULTS_H_
23#define INCLUDE_EXADG_UTILITIES_PRINT_SOLVER_RESULTS_H_
24
25// C/C++
26#include <iostream>
27
28// deal.II
29#include <deal.II/base/conditional_ostream.h>
30#include <deal.II/base/mpi.h>
31#include <deal.II/base/utilities.h>
32
33// ExaDG
34#include <exadg/utilities/print_functions.h>
35
36namespace ExaDG
37{
38inline void
39print_throughput(
40 std::vector<std::tuple<unsigned int, dealii::types::global_dof_index, double>> const & wall_times,
41 std::string const & operator_type,
42 MPI_Comm const & mpi_comm)
43{
44 unsigned int N_mpi_processes = dealii::Utilities::MPI::n_mpi_processes(mpi_comm);
45
46 if(dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0)
47 {
48 // clang-format off
49 std::cout << std::endl
50 << print_horizontal_line()
51 << std::endl << std::endl
52 << "Operator type: " << operator_type
53 << std::endl << std::endl
54 << std::setw(5) << std::left << "k"
55 << std::setw(15) << std::left << "DoFs"
56 << std::setw(15) << std::left << "DoFs/sec"
57 << std::setw(15) << std::left << "DoFs/(sec*core)"
58 << std::endl << std::flush;
59
60 typedef typename std::vector<std::tuple<unsigned int, dealii::types::global_dof_index, double> >::const_iterator ITERATOR;
61 for(ITERATOR it = wall_times.begin(); it != wall_times.end(); ++it)
62 {
63 std::cout << std::setw(5) << std::left << std::get<0>(*it)
64 << std::scientific << std::setprecision(4)
65 << std::setw(15) << std::left << (double)std::get<1>(*it)
66 << std::setw(15) << std::left << std::get<2>(*it)
67 << std::setw(15) << std::left << std::get<2>(*it)/(double)N_mpi_processes
68 << std::endl << std::flush;
69 }
70
71 std::cout << print_horizontal_line() << std::endl << std::endl << std::flush;
72 // clang-format on
73 }
74}
75
76inline void
77print_throughput_steady(dealii::ConditionalOStream const & pcout,
78 dealii::types::global_dof_index const n_dofs,
79 double const overall_time_avg,
80 unsigned int const N_mpi_processes)
81{
82 // clang-format off
83 pcout << std::endl
84 << "Throughput:" << std::endl
85 << " Number of MPI processes = " << N_mpi_processes << std::endl
86 << " Degrees of freedom = " << n_dofs << std::endl
87 << " Wall time = " << std::scientific << std::setprecision(2) << overall_time_avg << " s" << std::endl
88 << " Throughput = " << std::scientific << std::setprecision(2) << n_dofs / (overall_time_avg * N_mpi_processes) << " DoFs/s/core" << std::endl
89 << std::flush;
90 // clang-format on
91}
92
93inline void
94print_throughput_10(dealii::ConditionalOStream const & pcout,
95 dealii::types::global_dof_index const n_dofs,
96 double const t_10,
97 unsigned int const N_mpi_processes)
98{
99 double const tau_10 = t_10 * (double)N_mpi_processes / n_dofs;
100
101 // clang-format off
102 pcout << std::endl
103 << "Throughput of linear solver (numbers based on n_10):" << std::endl
104 << " Number of MPI processes = " << N_mpi_processes << std::endl
105 << " Degrees of freedom = " << n_dofs << std::endl
106 << " Wall time t_10 = " << std::scientific << std::setprecision(2) << t_10 << " s" << std::endl
107 << " tau_10 = " << std::scientific << std::setprecision(2) << tau_10 << " s*core/DoF" << std::endl
108 << " Throughput E_10 = " << std::scientific << std::setprecision(2) << 1.0 / tau_10 << " DoF/s/core" << std::endl
109 << std::flush;
110 // clang-format on
111}
112
113inline void
114print_throughput_unsteady(dealii::ConditionalOStream const & pcout,
115 dealii::types::global_dof_index const n_dofs,
116 double const overall_time_avg,
117 unsigned int const N_time_steps,
118 unsigned int const N_mpi_processes)
119{
120 double const time_per_timestep = overall_time_avg / (double)N_time_steps;
121
122 // clang-format off
123 pcout << std::endl
124 << "Throughput per time step:" << std::endl
125 << " Number of MPI processes = " << N_mpi_processes << std::endl
126 << " Degrees of freedom = " << n_dofs << std::endl
127 << " Wall time = " << std::scientific << std::setprecision(2) << overall_time_avg << " s" << std::endl
128 << " Time steps = " << std::left << N_time_steps << std::endl
129 << " Wall time per time step = " << std::scientific << std::setprecision(2) << time_per_timestep << " s" << std::endl
130 << " Throughput = " << std::scientific << std::setprecision(2) << n_dofs / (time_per_timestep * N_mpi_processes) << " DoFs/s/core" << std::endl
131 << std::flush;
132 // clang-format on
133}
134
135inline void
136print_throughput_unsteady(dealii::ConditionalOStream const & pcout,
137 double const avg_n_dofs,
138 double const overall_time_avg,
139 unsigned int const N_time_steps,
140 unsigned int const N_mpi_processes)
141{
142 double const time_per_timestep = overall_time_avg / (double)N_time_steps;
143
144 // clang-format off
145 pcout << std::endl
146 << "Throughput per time step:" << std::endl
147 << " Number of MPI processes = " << N_mpi_processes << std::endl
148 << " Average Degrees of freedom = " << std::scientific << std::setprecision(2)<< avg_n_dofs << std::endl
149 << " Wall time = " << std::scientific << std::setprecision(2) << overall_time_avg << " s" << std::endl
150 << " Time steps = " << std::left << N_time_steps << std::endl
151 << " Wall time per time step = " << std::scientific << std::setprecision(2) << time_per_timestep << " s" << std::endl
152 << " Throughput = " << std::scientific << std::setprecision(2) << avg_n_dofs / (time_per_timestep * N_mpi_processes) << " DoFs/s/core" << std::endl
153 << std::flush;
154 // clang-format on
155}
156
157inline void
158print_costs(dealii::ConditionalOStream const & pcout,
159 double const overall_time_avg,
160 unsigned int const N_mpi_processes)
161
162{
163 // clang-format off
164 pcout << std::endl
165 << "Computational costs:" << std::endl
166 << " Number of MPI processes = " << N_mpi_processes << std::endl
167 << " Wall time = " << std::scientific << std::setprecision(2) << overall_time_avg << " s" << std::endl
168 << " Computational costs = " << std::scientific << std::setprecision(2) << overall_time_avg * (double)N_mpi_processes / 3600.0 << " CPUh" << std::endl
169 << std::flush;
170 // clang-format on
171}
172
173inline void
174print_solver_info_nonlinear(dealii::ConditionalOStream const & pcout,
175 unsigned int const N_iter_nonlinear,
176 unsigned int const N_iter_linear,
177 double const wall_time)
178
179{
180 double const N_iter_linear_avg =
181 (N_iter_nonlinear > 0) ? double(N_iter_linear) / double(N_iter_nonlinear) : N_iter_linear;
182
183 // clang-format off
184 pcout << std::endl
185 << " Newton iterations: " << std::setw(12) << std::right << N_iter_nonlinear << std::endl
186 << " Linear iterations (avg):" << std::setw(12) << std::fixed << std::setprecision(1) << std::right << N_iter_linear_avg << std::endl
187 << " Linear iterations (tot):" << std::setw(12) << std::right << N_iter_linear << std::endl
188 << " Wall time [s]: " << std::setw(12) << std::scientific << std::setprecision(2) << std::right << wall_time << std::endl
189 << std::flush;
190 // clang-format on
191}
192
193inline void
194print_solver_info_linear(dealii::ConditionalOStream const & pcout,
195 unsigned int const N_iter_linear,
196 double const wall_time)
197
198{
199 // clang-format off
200 pcout << std::endl
201 << " Iterations: " << std::setw(12) << std::right << N_iter_linear << std::endl
202 << " Wall time [s]:" << std::setw(12) << std::scientific << std::setprecision(2) << std::right << wall_time << std::endl
203 << std::flush;
204 // clang-format on
205}
206
207inline void
208print_wall_time(dealii::ConditionalOStream const & pcout, double const wall_time)
209
210{
211 // clang-format off
212 pcout << std::endl
213 << " Wall time [s]:" << std::setw(12) << std::scientific << std::setprecision(2) << std::right << wall_time << std::endl
214 << std::flush;
215 // clang-format on
216}
217
218inline void
219print_list_of_iterations(dealii::ConditionalOStream const & pcout,
220 std::vector<std::string> const & names,
221 std::vector<double> const & iterations_avg)
222{
223 unsigned int length = 1;
224 for(unsigned int i = 0; i < names.size(); ++i)
225 {
226 length = length > names[i].length() ? length : names[i].length();
227 }
228
229 // print
230 for(unsigned int i = 0; i < iterations_avg.size(); ++i)
231 {
232 pcout << " " << std::setw(length + 2) << std::left << names[i] << std::fixed
233 << std::setprecision(2) << std::right << std::setw(6) << iterations_avg[i] << std::endl;
234 }
235}
236
238{
239 SolverResult() : degree(1), dofs(1), n_10(0), tau_10(0.0)
240 {
241 }
242
243 SolverResult(unsigned int const degree_,
244 dealii::types::global_dof_index const dofs_,
245 double const n_10_,
246 double const tau_10_)
247 : degree(degree_), dofs(dofs_), n_10(n_10_), tau_10(tau_10_)
248 {
249 }
250
251 static void
252 print_header(dealii::ConditionalOStream const & pcout)
253 {
254 // names
255 pcout << std::setw(7) << "degree";
256 pcout << std::setw(15) << "dofs";
257 pcout << std::setw(8) << "n_10";
258 pcout << std::setw(15) << "tau_10";
259 pcout << std::setw(15) << "throughput";
260 pcout << std::endl;
261
262 // units
263 pcout << std::setw(7) << " ";
264 pcout << std::setw(15) << " ";
265 pcout << std::setw(8) << " ";
266 pcout << std::setw(15) << "in s*core/DoF";
267 pcout << std::setw(15) << "in DoF/s/core";
268 pcout << std::endl;
269
270 pcout << std::endl;
271 }
272
273 void
274 print(dealii::ConditionalOStream const & pcout) const
275 {
276 pcout << std::setw(7) << std::fixed << degree;
277 pcout << std::setw(15) << std::fixed << dofs;
278 pcout << std::setw(8) << std::fixed << std::setprecision(1) << n_10;
279 pcout << std::setw(15) << std::scientific << std::setprecision(2) << tau_10;
280 pcout << std::setw(15) << std::scientific << std::setprecision(2) << 1.0 / tau_10;
281 pcout << std::endl;
282 }
283
284 unsigned int degree;
285 dealii::types::global_dof_index dofs;
286 double n_10;
287 double tau_10;
288};
289
290inline void
291print_results(std::vector<SolverResult> const & results, MPI_Comm const & mpi_comm)
292{
293 // summarize results for all polynomial degrees and problem sizes
294 dealii::ConditionalOStream pcout(std::cout,
295 dealii::Utilities::MPI::this_mpi_process(mpi_comm) == 0);
296
297 pcout << std::endl << print_horizontal_line() << std::endl << std::endl;
298
299 pcout << "Summary of results:" << std::endl << std::endl;
300
301 SolverResult::print_header(pcout);
302 for(std::vector<SolverResult>::const_iterator it = results.begin(); it != results.end(); ++it)
303 it->print(pcout);
304
305 pcout << print_horizontal_line() << std::endl << std::endl;
306}
307
308} // namespace ExaDG
309
310#endif /* INCLUDE_EXADG_UTILITIES_PRINT_SOLVER_RESULTS_H_ */
Definition driver.cpp:33
Definition print_solver_results.h:238