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_array.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{
46template <size_t MaxNumEvents>
48: public base<papi_array<MaxNumEvents>, std::array<long long, MaxNumEvents>>
49, private policy::instance_tracker<papi_array<MaxNumEvents>>
50, private papi_common
51{
52 using size_type = size_t;
53 using event_list = std::vector<int>;
54 using value_type = std::array<long long, MaxNumEvents>;
55 using entry_type = typename value_type::value_type;
60 using get_initializer_t = std::function<event_list()>;
61 using common_type = void;
62
63 static const short precision = 3;
64 static const short width = 8;
65
66 template <typename Tp>
67 using array_t = std::array<Tp, MaxNumEvents>;
68
69 friend struct operation::record<this_type>;
70 friend struct operation::start<this_type>;
71 friend struct operation::stop<this_type>;
72 friend struct operation::set_started<this_type>;
73 friend struct operation::set_stopped<this_type>;
74
75 //----------------------------------------------------------------------------------//
76
77 static auto& get_initializer() { return papi_common::get_initializer<common_type>(); }
78 static void configure()
79 {
80 if(!is_configured<common_type>())
81 papi_common::initialize<common_type>();
82 }
83 static void initialize() { configure(); }
84 static void thread_finalize()
85 {
86 papi_common::finalize<common_type>();
88 }
89 static void finalize() { papi_common::finalize<common_type>(); }
90
91 //----------------------------------------------------------------------------------//
92
93 papi_array() { events = get_events<common_type>(); }
94 ~papi_array() = default;
95 papi_array(const papi_array&) = default;
96 papi_array(papi_array&&) noexcept = default;
97 papi_array& operator=(const papi_array&) = default;
98 papi_array& operator=(papi_array&&) noexcept = default;
99
100 using base_type::load;
101
102 //----------------------------------------------------------------------------------//
103
104 size_t size() { return events.size(); }
105
106 //----------------------------------------------------------------------------------//
107
109 {
110 value_type read_value{};
111 read_value.fill(0);
112 if(is_configured<common_type>())
113 papi::read(event_set<common_type>(), read_value.data());
114 return read_value;
115 }
116
117 //----------------------------------------------------------------------------------//
118
119 template <typename Tp = double>
120 std::vector<Tp> get() const
121 {
122 std::vector<Tp> values;
123 auto& _data = load();
124 values.reserve(_data.size());
125 for(auto& itr : _data)
126 values.emplace_back(itr);
127 values.resize(events.size());
128 return values;
129 }
130
131 //----------------------------------------------------------------------------------//
132 // sample
133 //
134 void sample()
135 {
136 if(tracker_type::get_thread_started() == 0)
137 configure();
138 if(events.empty())
139 events = get_events<common_type>();
140
142 value = record();
143 }
144
145 //----------------------------------------------------------------------------------//
146 // start
147 //
148 void start()
149 {
150 if(tracker_type::get_thread_started() == 0 || events.size() == 0)
151 configure();
152
153 events = get_events<common_type>();
155 value = record();
156 }
157
158 //----------------------------------------------------------------------------------//
159
160 void stop()
161 {
163 using namespace tim::component::operators;
164 value = (record() - value);
165 accum += value;
166 }
167
168 //----------------------------------------------------------------------------------//
169
171 {
172 for(size_type i = 0; i < events.size(); ++i)
173 accum[i] += rhs.accum[i];
174 for(size_type i = 0; i < events.size(); ++i)
175 value[i] += rhs.value[i];
176 return *this;
177 }
178
179 //----------------------------------------------------------------------------------//
180
182 {
183 for(size_type i = 0; i < events.size(); ++i)
184 accum[i] -= rhs.accum[i];
185 for(size_type i = 0; i < events.size(); ++i)
186 value[i] -= rhs.value[i];
187 return *this;
188 }
189
190 //----------------------------------------------------------------------------------//
191
192 this_type& operator/=(size_t _val)
193 {
194 for(size_type i = 0; i < events.size(); ++i)
195 accum[i] /= _val;
196 for(size_type i = 0; i < events.size(); ++i)
197 value[i] /= _val;
198 return *this;
199 }
200
201 //----------------------------------------------------------------------------------//
202
203protected:
204 using base_type::accum;
205 using base_type::laps;
208 using base_type::value;
210
211 friend struct base<this_type, value_type>;
212 friend class impl::storage<this_type,
213 trait::uses_value_storage<this_type, value_type>::value>;
214
215public:
216 //==================================================================================//
217 //
218 // data representation
219 //
220 //==================================================================================//
221
223 {
224 return "papi_array" + std::to_string((event_set<common_type>() < 0)
225 ? 0
226 : event_set<common_type>());
227 }
228
229 static std::string description() { return "Fixed-size array of PAPI HW counters"; }
230
231 TIMEMORY_NODISCARD entry_type get_display(int evt_type) const
232 {
233 return accum.at(evt_type);
234 }
235
236 //----------------------------------------------------------------------------------//
237 // serialization
238 //
239 template <typename Archive>
240 void load(Archive& ar, const unsigned int)
241 {
242 ar(cereal::make_nvp("laps", laps), cereal::make_nvp("value", value),
243 cereal::make_nvp("accum", accum), cereal::make_nvp("events", events));
244 }
245
246 //----------------------------------------------------------------------------------//
247 // serialization
248 //
249 template <typename Archive>
250 void save(Archive& ar, const unsigned int) const
251 {
252 array_t<double> _disp;
253 for(size_type i = 0; i < events.size(); ++i)
254 _disp[i] = get_display(i);
255 ar(cereal::make_nvp("laps", laps), cereal::make_nvp("repr_data", _disp),
256 cereal::make_nvp("value", value), cereal::make_nvp("accum", accum),
257 cereal::make_nvp("display", _disp), cereal::make_nvp("events", events));
258 }
259
260 //----------------------------------------------------------------------------------//
261 // array of descriptions
262 //
263 TIMEMORY_NODISCARD std::vector<std::string> label_array() const
264 {
265 std::vector<std::string> arr(events.size());
266 for(size_type i = 0; i < events.size(); ++i)
267 arr[i] = papi::get_event_info(events[i]).short_descr;
268
269 for(auto& itr : arr)
270 {
271 size_t n = std::string::npos;
272 while((n = itr.find("L/S")) != std::string::npos)
273 itr.replace(n, 3, "Loads_Stores");
274 }
275
276 for(auto& itr : arr)
277 {
278 size_t n = std::string::npos;
279 while((n = itr.find('/')) != std::string::npos)
280 itr.replace(n, 1, "_per_");
281 }
282
283 for(auto& itr : arr)
284 {
285 size_t n = std::string::npos;
286 while((n = itr.find(' ')) != std::string::npos)
287 itr.replace(n, 1, "_");
288
289 while((n = itr.find("__")) != std::string::npos)
290 itr.replace(n, 2, "_");
291 }
292
293 return arr;
294 }
295
296 //----------------------------------------------------------------------------------//
297 // array of labels
298 //
299 TIMEMORY_NODISCARD std::vector<std::string> description_array() const
300 {
301 std::vector<std::string> arr(events.size());
302 for(size_type i = 0; i < events.size(); ++i)
303 arr[i] = papi::get_event_info(events[i]).long_descr;
304 return arr;
305 }
306
307 //----------------------------------------------------------------------------------//
308 // array of unit
309 //
310 TIMEMORY_NODISCARD std::vector<std::string> display_unit_array() const
311 {
312 std::vector<std::string> arr(events.size());
313 for(size_type i = 0; i < events.size(); ++i)
314 arr[i] = papi::get_event_info(events[i]).units;
315 return arr;
316 }
317
318 //----------------------------------------------------------------------------------//
319 // array of unit values
320 //
321 TIMEMORY_NODISCARD std::vector<int64_t> unit_array() const
322 {
323 std::vector<int64_t> arr(events.size());
324 for(size_type i = 0; i < events.size(); ++i)
325 arr[i] = 1;
326 return arr;
327 }
328
329 //----------------------------------------------------------------------------------//
330
331 TIMEMORY_NODISCARD string_t get_display() const
332 {
333 if(events.size() == 0)
334 return "";
335 auto val = load();
336 auto _get_display = [&](std::ostream& os, size_type idx) {
337 auto _obj_value = val[idx];
338 auto _evt_type = events[idx];
339 string_t _label = papi::get_event_info(_evt_type).short_descr;
340 string_t _disp = papi::get_event_info(_evt_type).units;
341 auto _prec = base_type::get_precision();
342 auto _width = base_type::get_width();
343 auto _flags = base_type::get_format_flags();
344
345 std::stringstream ss;
346 std::stringstream ssv;
347 std::stringstream ssi;
348 ssv.setf(_flags);
349 ssv << std::setw(_width) << std::setprecision(_prec) << _obj_value;
350 if(!_disp.empty())
351 ssv << " " << _disp;
352 if(!_label.empty())
353 ssi << " " << _label;
354 ss << ssv.str() << ssi.str();
355 os << ss.str();
356 };
357
358 std::stringstream ss;
359 for(size_type i = 0; i < events.size(); ++i)
360 {
361 _get_display(ss, i);
362 if(i + 1 < events.size())
363 ss << ", ";
364 }
365 return ss.str();
366 }
367
368 //----------------------------------------------------------------------------------//
369
370 friend std::ostream& operator<<(std::ostream& os, const this_type& obj)
371 {
372 if(obj.events.size() == 0)
373 return os;
374 // output the metrics
375 auto _value = obj.get_display();
376 auto _label = this_type::get_label();
377 auto _disp = this_type::display_unit();
378 auto _prec = this_type::get_precision();
379 auto _width = this_type::get_width();
380 auto _flags = this_type::get_format_flags();
381
382 std::stringstream ss_value;
383 std::stringstream ss_extra;
384 ss_value.setf(_flags);
385 ss_value << std::setw(_width) << std::setprecision(_prec) << _value;
386 if(!_disp.empty())
387 {
388 ss_extra << " " << _disp;
389 }
390 else if(!_label.empty())
391 {
392 ss_extra << " " << _label;
393 }
394 os << ss_value.str() << ss_extra.str();
395 return os;
396 }
397};
398} // namespace component
399} // 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
static short get_precision()
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
this_type & operator-=(const this_type &rhs)
Definition: papi_array.hpp:181
std::function< event_list()> get_initializer_t
Definition: papi_array.hpp:60
friend std::ostream & operator<<(std::ostream &os, const this_type &obj)
Definition: papi_array.hpp:370
std::vector< std::string > label_array() const
Definition: papi_array.hpp:263
static std::string label()
Definition: papi_array.hpp:222
std::array< long long, MaxNumEvents > value_type
Definition: papi_array.hpp:54
this_type & operator+=(const this_type &rhs)
Definition: papi_array.hpp:170
string_t get_display() const
Definition: papi_array.hpp:331
std::vector< std::string > display_unit_array() const
Definition: papi_array.hpp:310
std::vector< int64_t > unit_array() const
Definition: papi_array.hpp:321
papi_array(papi_array &&) noexcept=default
std::vector< Tp > get() const
Definition: papi_array.hpp:120
typename value_type::value_type entry_type
Definition: papi_array.hpp:55
static const short width
Definition: papi_array.hpp:64
std::vector< std::string > description_array() const
Definition: papi_array.hpp:299
std::array< Tp, MaxNumEvents > array_t
Definition: papi_array.hpp:67
this_type & operator/=(size_t _val)
Definition: papi_array.hpp:192
static std::string description()
Definition: papi_array.hpp:229
static const short precision
Definition: papi_array.hpp:63
void save(Archive &ar, const unsigned int) const
Definition: papi_array.hpp:250
entry_type get_display(int evt_type) const
Definition: papi_array.hpp:231
void load(Archive &ar, const unsigned int)
Definition: papi_array.hpp:240
std::vector< int > event_list
Definition: papi_array.hpp:53
papi_array(const papi_array &)=default
static value_type record()
Definition: papi_array.hpp:108
papi_array< MaxNumEvents > this_type
Definition: papi_array.hpp:56
static void thread_finalize()
Definition: papi_array.hpp:84
static auto & get_initializer()
Definition: papi_array.hpp:77
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