timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
papi_tuple.hpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25#pragma once
26
28#include "timemory/components/papi/backends.hpp"
33#include "timemory/units.hpp"
34
35#include <array>
36#include <functional>
37#include <memory>
38#include <sstream>
39#include <string>
40#include <vector>
41
42namespace tim
43{
44namespace component
45{
46/// \struct tim::component::papi_tuple
47/// \tparam EventTypes Compile-time constant list of PAPI event identifiers
48///
49/// \brief This component is useful for bundling together a fixed set of hardware counter
50/// identifiers which require no runtime configuration
51///
52/// \code{.cpp}
53/// // the "Instructions" alias below explicitly collects the total instructions,
54/// // the number of load instructions, the number of store instructions
55/// using Instructions = papi_tuple<PAPI_TOT_INS, PAPI_LD_INS, PAPI_SR_INS>;
56///
57/// Instructions inst{};
58/// inst.start();
59/// ...
60/// inst.stop();
61/// std::vector<double> data = inst.get();
62///
63/// \endcode
64template <int... EventTypes>
66: public base<papi_tuple<EventTypes...>, std::array<long long, sizeof...(EventTypes)>>
67, private policy::instance_tracker<papi_tuple<EventTypes...>>
68, private papi_common
69{
70 using size_type = std::size_t;
71 using value_type = std::array<long long, sizeof...(EventTypes)>;
72 using entry_type = typename value_type::value_type;
73 using this_type = papi_tuple<EventTypes...>;
78
79 static const size_type num_events = sizeof...(EventTypes);
80 template <typename Tp>
81 using array_t = std::array<Tp, num_events>;
82
83 friend struct operation::record<this_type>;
84 friend struct operation::start<this_type>;
85 friend struct operation::stop<this_type>;
86 friend struct operation::set_started<this_type>;
87 friend struct operation::set_stopped<this_type>;
88
89public:
90 //----------------------------------------------------------------------------------//
91
92 static void configure()
93 {
94 if(!is_configured<common_type>())
95 {
96 papi_common::get_initializer<common_type>() = []() {
97 return std::vector<int>({ EventTypes... });
98 };
99 papi_common::get_events<common_type>() = { EventTypes... };
100 papi_common::initialize<common_type>();
101 }
102 }
104 static void thread_finalize()
105 {
106 papi_common::finalize<common_type>();
108 }
109 static void initialize() { configure(); }
110 static void finalize() { papi_common::finalize<common_type>(); }
111
112 //----------------------------------------------------------------------------------//
113
115 {
116 if(is_configured<common_type>())
117 tim::papi::read(event_set<common_type>(), get_read_values().data());
118 return get_read_values();
119 }
120
121private:
122 static value_type& get_read_values()
123 {
124 static thread_local value_type _instance = []() {
125 value_type values;
127 return values;
128 }();
129 return _instance;
130 }
131
132protected:
133 using base_type::accum;
134 using base_type::laps;
137 using base_type::value;
138
139 friend struct base<this_type, value_type>;
140 friend class impl::storage<this_type,
141 trait::uses_value_storage<this_type, value_type>::value>;
142
143public:
144 //==================================================================================//
145 //
146 // construction
147 //
148 //==================================================================================//
149
150 TIMEMORY_DEFAULT_OBJECT(papi_tuple)
151
152 using base_type::load;
153
154 //----------------------------------------------------------------------------------//
155 // sample
156 //
157 void sample()
158 {
159 if(tracker_type::get_thread_started() == 0)
160 configure();
161 if(events.empty())
162 events = get_events<common_type>();
163
165 value = record();
166 }
167
168 //----------------------------------------------------------------------------------//
169 // start
170 //
171 void start()
172 {
173 if(tracker_type::get_thread_started() == 0 || events.size() == 0)
174 {
175 configure();
176 events = get_events<common_type>();
177 }
178
180 value = record();
181 }
182
183 //----------------------------------------------------------------------------------//
184 // start
185 //
186 void stop()
187 {
189 using namespace tim::component::operators;
190 value = (record() - value);
191 accum += value;
192 }
193
194 //----------------------------------------------------------------------------------//
195 // operators
196 //
198 {
199 for(size_type i = 0; i < num_events; ++i)
200 accum[i] += rhs.accum[i];
201 for(size_type i = 0; i < num_events; ++i)
202 value[i] += rhs.value[i];
203 return *this;
204 }
205
207 {
208 for(size_type i = 0; i < num_events; ++i)
209 accum[i] -= rhs.accum[i];
210 for(size_type i = 0; i < num_events; ++i)
211 value[i] -= rhs.value[i];
212 return *this;
213 }
214
215public:
216 //==================================================================================//
217 //
218 // data representation
219 //
220 //==================================================================================//
221 static const short precision = 3;
222 static const short width = 12;
223
224 // leave these empty
226 {
227 return "papi" + std::to_string(event_set<common_type>());
228 }
229 static std::string description() { return ""; }
230 static std::string display_unit() { return ""; }
231 static int64_t unit() { return 1; }
232
233 //----------------------------------------------------------------------------------//
234 // serialization
235 //
236 template <typename Archive>
237 void serialize(Archive& ar, const unsigned int)
238 {
239 array_t<double> _disp;
240 array_t<double> _value;
241 array_t<double> _accum;
242 for(size_type i = 0; i < num_events; ++i)
243 {
244 _disp[i] = get_display(i);
245 _value[i] = value[i];
246 _accum[i] = accum[i];
247 }
248 ar(cereal::make_nvp("laps", laps), cereal::make_nvp("repr_data", _disp),
249 cereal::make_nvp("value", _value), cereal::make_nvp("accum", _accum),
250 cereal::make_nvp("display", _disp));
251 }
252
253 entry_type get_display(int evt_type) const { return accum[evt_type]; }
254
255 TIMEMORY_NODISCARD string_t get_display() const
256 {
257 auto val = load();
258 auto _get_display = [&](std::ostream& os, size_type idx) {
259 auto _obj_value = val[idx];
260 auto _evt_type = std::vector<int>({ EventTypes... }).at(idx);
261 string_t _label = papi::get_event_info(_evt_type).short_descr;
262 string_t _disp = papi::get_event_info(_evt_type).units;
263 auto _prec = base_type::get_precision();
264 auto _width = base_type::get_width();
265 auto _flags = base_type::get_format_flags();
266
267 std::stringstream ss;
268 std::stringstream ssv;
269 std::stringstream ssi;
270 ssv.setf(_flags);
271 ssv << std::setw(_width) << std::setprecision(_prec) << _obj_value;
272 if(!_disp.empty())
273 {
274 ssv << " " << _disp;
275 }
276 else if(!_label.empty())
277 {
278 ssi << " " << _label;
279 }
280 ss << ssv.str() << ssi.str();
281 os << ss.str();
282 };
283 std::stringstream ss;
284 for(size_type i = 0; i < num_events; ++i)
285 {
286 _get_display(ss, i);
287 if(i + 1 < num_events)
288 ss << ", ";
289 }
290 return ss.str();
291 }
292
293 template <typename Lhs, typename Rhs, size_t N, size_t... Idx>
294 static void convert(std::array<Lhs, N>& lhs, const std::array<Rhs, N>& rhs,
295 std::index_sequence<Idx...>)
296 {
297 TIMEMORY_FOLD_EXPRESSION(std::get<Idx>(lhs) =
298 static_cast<Lhs>(std::get<Idx>(rhs)));
299 }
300 template <typename Tp = double>
301 auto get() const
302 {
303 std::array<Tp, num_events> values;
304 auto& _data = load();
305 convert(values, _data, std::make_index_sequence<num_events>{});
306 return values;
307 }
308
309 //----------------------------------------------------------------------------------//
310 // array of descriptions
311 //
313 {
315 for(size_type i = 0; i < num_events; ++i)
316 arr[i] = papi::get_event_info(get_events<common_type>().at(i)).short_descr;
317 return arr;
318 }
319
320 //----------------------------------------------------------------------------------//
321 // array of labels
322 //
324 {
326 for(size_type i = 0; i < num_events; ++i)
327 arr[i] = papi::get_event_info(get_events<common_type>().at(i)).long_descr;
328 return arr;
329 }
330
331 //----------------------------------------------------------------------------------//
332 // array of unit
333 //
335 {
337 for(size_type i = 0; i < num_events; ++i)
338 arr[i] = papi::get_event_info(get_events<common_type>().at(i)).units;
339 return arr;
340 }
341
342 //----------------------------------------------------------------------------------//
343 // array of unit values
344 //
346 {
348 for(size_type i = 0; i < num_events; ++i)
349 arr[i] = 1;
350 return arr;
351 }
352};
353} // namespace component
354} // namespace tim
Declare the papi component types.
void stop(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:386
void start(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:316
Inherit from this policy to add reference counting support. Useful if you want to turn a global setti...
Definition: types.hpp:406
Definition: kokkosp.cpp:39
std::string string_t
Definition: utility.hpp:98
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
const std::string std::ostream * os
_args at(0)
static short get_precision()
decltype(auto) load()
void set_stopped()
store that stop has been called
static short get_width()
static fmtflags get_format_flags()
storage< Tp, Value > storage_type
void set_started()
store that start has been called
A very lightweight storage class which provides nothing.
Definition: declaration.hpp:51
static common_data & data()
typename value_type::value_type entry_type
Definition: papi_common.hpp:65
std::array< Tp, N > array_t
Definition: papi_common.hpp:60
vector_t< long long > value_type
Definition: papi_common.hpp:64
This component is useful for bundling together a fixed set of hardware counter identifiers which requ...
Definition: papi_tuple.hpp:69
std::array< long long, sizeof...(EventTypes)> value_type
Definition: papi_tuple.hpp:71
papi_tuple< EventTypes... > this_type
Definition: papi_tuple.hpp:73
static std::string label()
Definition: papi_tuple.hpp:225
static void convert(std::array< Lhs, N > &lhs, const std::array< Rhs, N > &rhs, std::index_sequence< Idx... >)
Definition: papi_tuple.hpp:294
entry_type get_display(int evt_type) const
Definition: papi_tuple.hpp:253
static array_t< std::string > description_array()
Definition: papi_tuple.hpp:323
static value_type record()
Definition: papi_tuple.hpp:114
void serialize(Archive &ar, const unsigned int)
Definition: papi_tuple.hpp:237
static const short precision
Definition: papi_tuple.hpp:221
static const short width
Definition: papi_tuple.hpp:222
static array_t< std::string > display_unit_array()
Definition: papi_tuple.hpp:334
this_type & operator-=(const this_type &rhs)
Definition: papi_tuple.hpp:206
this_type & operator+=(const this_type &rhs)
Definition: papi_tuple.hpp:197
static std::string description()
Definition: papi_tuple.hpp:229
static array_t< std::string > label_array()
Definition: papi_tuple.hpp:312
static const size_type num_events
Definition: papi_tuple.hpp:79
string_t get_display() const
Definition: papi_tuple.hpp:255
static std::string display_unit()
Definition: papi_tuple.hpp:230
static void thread_finalize()
Definition: papi_tuple.hpp:104
static array_t< int64_t > unit_array()
Definition: papi_tuple.hpp:345
This operation attempts to call a member function which the component provides to internally store wh...
Definition: types.hpp:469
This operation attempts to call a member function which the component provides to internally store wh...
Definition: types.hpp:502
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56