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