KaMPIng 0.1.1
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
printer.hpp
1// This file is part of KaMPIng.
2//
3// Copyright 2023 The KaMPIng Authors
4//
5// KaMPIng is free software : you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
7// version. KaMPIng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
9// for more details.
10//
11// You should have received a copy of the GNU Lesser General Public License along with KaMPIng. If not, see
12// <https://www.gnu.org/licenses/>.
13
14#pragma once
15
16#include <iostream>
17#include <ostream>
18#include <variant>
19#include <vector>
20
22
23namespace kamping::measurements {
24
25/// @brief Puts quotation marks around a given string.
26/// @param str String to be quoted.
27/// @return Quoted string.
28inline std::string quote_string(std::string const& str) {
29 return "\"" + str + "\"";
30}
31
32namespace internal {
33/// @brief Able to print either a single value or a vector of value to the given outstream.
34/// @tparam Value type to print.
35template <typename T>
37 /// @brief Constructs a printer printing to the given outstream.
38 /// @param outstream Outstream to print on.
40
41 /// @brief Outputs the content of the given vector to outstream.
42 /// @param vec Vector whose elements are comma-separated printed to the outstream.
43 void operator()(std::vector<T> const& vec) const {
44 _outstream << "[";
45 bool is_first = true;
46 for (auto const& elem: vec) {
47 if (!is_first) {
48 _outstream << ", ";
49 }
50 is_first = false;
51 _outstream << std::fixed << elem;
52 }
53 _outstream << "]";
54 }
55
56 /// @brief Outputs the given scalar to outstream.
57 /// @param scalar Scalar to be printed.
58 void operator()(T const& scalar) const {
59 _outstream << std::fixed << scalar;
60 }
61 std::ostream& _outstream; ///< Outstream used for printing.
62};
63} // namespace internal
64
65/// @brief Printer class that prints an evaluated TimerTree in Json format.
66///
67/// @tparam Duration Type to represent a duration.
68template <typename Duration = double>
70public:
71 /// @brief Construct a printer that use std::cout as outstream.
72 SimpleJsonPrinter() : _outstream{std::cout}, _internal_printer(_outstream) {}
73
74 /// @brief Construct a printer printing to a given outstream.
75 ///
76 /// @param outstream Outstream on which the content is printed.
77 SimpleJsonPrinter(std::ostream& outstream) : _outstream{outstream}, _internal_printer(_outstream) {}
78
79 /// @brief Construct a printer printing to a given outstream and adding
80 /// additional configuration info.
81 ///
82 /// @param outstream Outstream on which the content is printed.
83 /// @param config_info Additional configuration info (vector of key-value pairs), which will be printed as a
84 /// "config" - dict by the printer.
85 SimpleJsonPrinter(std::ostream& outstream, std::vector<std::pair<std::string, std::string>> config_info)
86 : _outstream{outstream},
87 _internal_printer(_outstream),
88 _config_info{config_info} {}
89
90 /// @brief Prints an evaluated TimerTree in Json format to stdout.
91 /// @param node Root node of the TimerTree to print.
92 /// @param indentation Indentation to use for the node.
93 void print(AggregatedTreeNode<Duration> const& node, std::size_t indentation = 0) {
94 _outstream << std::string(indentation, ' ') << "{" << std::endl;
95 _outstream << std::string(indentation + indentation_per_level, ' ') << quote_string("data") << ": {"
96 << std::endl;
97 print_impl(node, indentation + indentation_per_level + indentation_per_level);
98 _outstream << std::endl;
99 _outstream << std::string(indentation + indentation_per_level, ' ') << "}," << std::endl;
100 print_config(indentation + indentation_per_level);
101
102 _outstream << std::string(indentation, ' ') << "}";
103 }
104
105private:
106 std::ostream& _outstream; ///< Outstream to print on.
107 std::size_t indentation_per_level = 2u;
108 internal::ScalarOrVectorPrinter<Duration> _internal_printer; ///< Internal printer able to print either a scalar or
109 ///< vector of durations.
110 std::vector<std::pair<std::string, std::string>> _config_info;
111
112 void print_config(std::size_t indentation) {
113 _outstream << std::boolalpha;
114 _outstream << std::string(indentation, ' ') << quote_string("config") << ": {";
115 if (_config_info.empty()) {
116 // close dict in same line if config is empty and return
117 _outstream << "}" << std::endl;
118 return;
119 }
120 // otherwise output config in new line
121 _outstream << std::endl;
122 bool is_first = true;
123 for (auto const& [key, value]: _config_info) {
124 if (!is_first) {
125 _outstream << "," << std::endl;
126 }
127 is_first = false;
128 _outstream << std::string(indentation + indentation_per_level, ' ') << quote_string(key) << ":"
129 << quote_string(value);
130 }
131 _outstream << std::endl << std::string(indentation, ' ') << "}" << std::endl;
132 }
133
134 /// @brief Prints an evaluated TimerTree in Json format to stdout.
135 /// @param node Root node of the TimerTree to print.
136 /// @param indentation Indentation to use for the node.
137 void print_impl(AggregatedTreeNode<Duration> const& node, std::size_t indentation = 0) {
138 auto name = node.name();
139 auto evaluation_data = node.aggregated_data();
140 _outstream << std::string(indentation, ' ') << quote_string(name) << ": {" << std::endl;
141 _outstream << std::string(indentation + indentation_per_level, ' ') << quote_string("statistics") << ": {"
142 << std::endl;
143 if (!evaluation_data.empty()) {
144 bool is_first_outer = true;
145 for (auto const& [op, data]: evaluation_data) {
146 if (!is_first_outer) {
147 _outstream << "," << std::endl;
148 }
149 is_first_outer = false;
150 _outstream << std::string(indentation + 2 * indentation_per_level, ' ') << "\"" << get_string(op)
151 << "\""
152 << ": [";
153 bool is_first = true;
154 for (auto const& data_item: data) {
155 if (!is_first) {
156 _outstream << ", ";
157 }
158 is_first = false;
159 std::visit(_internal_printer, data_item);
160 }
161 _outstream << "]";
162 }
163 _outstream << std::endl;
164 }
165 _outstream << std::string(indentation + indentation_per_level, ' ') << "}";
166 if (!node.children().empty()) {
167 _outstream << ",";
168 }
169 _outstream << std::endl;
170
171 bool is_first = true;
172 for (auto const& children: node.children()) {
173 if (!is_first) {
174 _outstream << "," << std::endl;
175 }
176 is_first = false;
177 print_impl(*children, indentation + indentation_per_level);
178 }
179 if (!node.children().empty()) {
180 _outstream << std::endl;
181 }
182 _outstream << std::string(indentation, ' ') << "}";
183 }
184};
185
186/// @brief Printer class that prints an evaluated TimerTree in a flat format in which the timer hierarchy is collapsed
187/// into a dot separated identifier per measurement.
188///
189/// For example:
190/// \code
191/// timer.start("algo")
192/// timer.start("subroutine")
193/// timer.start("subsubroutine")
194/// timer.stop()
195/// timer.stop()
196/// timer.stop()
197/// \endcode
198/// will return an output conceptually similar to
199/// \code
200/// // algo=<duration data> algo.subroutine= <duration data> algo.subroutine.subsubroutine= <duration data> ...
201/// \endcode
202/// when printed with FlatPrinter.
203///
205public:
206 /// @brief Construct a printer that use std::cout as outstream.
207 FlatPrinter() : _outstream{std::cout} {}
208
209 /// @brief Construct a printer printing to a given outstream.
210 ///
211 /// @param outstream Outstream on which the content is printed.
212 FlatPrinter(std::ostream& outstream) : _outstream{outstream} {}
213 /// @brief Prints an evaluated TimerTree in Json format to stdout.
214 /// @tparam Duration Type to represent a duration.
215 /// @param node Root node of the TimerTree to print.
216 template <typename Duration>
218 _key_stack.push_back(node.name());
220 for (auto const& [operation, aggregated_data]: node.aggregated_data()) {
221 _outstream << " " << concatenate_key_stack() << ":" << get_string(operation) << "=[";
222 bool is_first = true;
223 for (auto const& data_item: aggregated_data) {
224 if (!is_first) {
225 _outstream << ", ";
226 }
227 is_first = false;
228 std::visit(internal_printer, data_item);
229 }
230 _outstream << "]";
231 }
232
233 for (auto const& child: node.children()) {
234 if (child) {
235 print(*child);
236 }
237 }
238 _key_stack.pop_back();
239 }
240
241private:
242 std::ostream& _outstream; ///< Outstream to print on.
243 std::vector<std::string> _key_stack; ///< Stack tracking the current path to the root.
244
245 std::string concatenate_key_stack() const {
246 std::string str;
247 for (auto const& key: _key_stack) {
248 if (!str.empty()) {
249 str.append(".");
250 }
251 str.append(key);
252 }
253 return str;
254 }
255};
256
257} // namespace kamping::measurements
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
Printer class that prints an evaluated TimerTree in a flat format in which the timer hierarchy is col...
Definition printer.hpp:204
FlatPrinter(std::ostream &outstream)
Construct a printer printing to a given outstream.
Definition printer.hpp:212
FlatPrinter()
Construct a printer that use std::cout as outstream.
Definition printer.hpp:207
void print(AggregatedTreeNode< Duration > const &node)
Prints an evaluated TimerTree in Json format to stdout.
Definition printer.hpp:217
Printer class that prints an evaluated TimerTree in Json format.
Definition printer.hpp:69
SimpleJsonPrinter(std::ostream &outstream, std::vector< std::pair< std::string, std::string > > config_info)
Construct a printer printing to a given outstream and adding additional configuration info.
Definition printer.hpp:85
void print(AggregatedTreeNode< Duration > const &node, std::size_t indentation=0)
Prints an evaluated TimerTree in Json format to stdout.
Definition printer.hpp:93
SimpleJsonPrinter()
Construct a printer that use std::cout as outstream.
Definition printer.hpp:72
SimpleJsonPrinter(std::ostream &outstream)
Construct a printer printing to a given outstream.
Definition printer.hpp:77
internal::OperationBuilder< Op, Commutative > op(Op &&op, Commutative commute=ops::internal::undefined_commutative_tag{})
Passes a reduction operation to ther underlying call. Accepts function objects, lambdas,...
Definition named_parameters.hpp:1155
std::string get_string(GlobalAggregationMode mode)
Returns name of given GlobalAggregationMode.
Definition measurement_aggregation_definitions.hpp:47
STL namespace.
Able to print either a single value or a vector of value to the given outstream.
Definition printer.hpp:36
ScalarOrVectorPrinter(std::ostream &outstream)
Constructs a printer printing to the given outstream.
Definition printer.hpp:39
void operator()(T const &scalar) const
Outputs the given scalar to outstream.
Definition printer.hpp:58
void operator()(std::vector< T > const &vec) const
Outputs the content of the given vector to outstream.
Definition printer.hpp:43
std::ostream & _outstream
Outstream used for printing.
Definition printer.hpp:61