timemory  3.2.1
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"
31 #include "timemory/mpl/policy.hpp"
32 #include "timemory/mpl/types.hpp"
33 #include "timemory/units.hpp"
34 
35 #include <functional>
36 #include <memory>
37 #include <sstream>
38 #include <string>
39 #include <vector>
40 
41 namespace tim
42 {
43 namespace 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 
203 protected:
204  // data types
205  using papi_common::events;
206 
207 public:
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:368
void start(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:298
Inherit from this policy to add reference counting support. Useful if you want to turn a global setti...
Definition: types.hpp:367
Definition: kokkosp.cpp:38
std::string string_t
Definition: utility.hpp:105
tim::mpl::apply< std::string > string
Definition: macros.hpp:52
static short get_precision()
static short get_width()
static fmtflags get_format_flags()
storage< Tp, Value > storage_type
Definition: declaration.hpp:90
Combines hardware counters and timers and executes the empirical roofline toolkit during application ...
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< int > event_list
Definition: papi_vector.hpp:61
static std::string description()
static std::string label()
papi_vector(const papi_vector &)=default
void save(Archive &ar, const unsigned int) const
vector_t< std::string > description_array() const
vector_t< std::string > label_array() const
vector_t< Tp > get() const
static auto & get_initializer()
Definition: papi_vector.hpp:84
void load(Archive &ar, const unsigned int)
papi_vector(papi_vector &&) noexcept=default
vector_t< std::string > display_unit_array() const
this_type & operator+=(const this_type &rhs)
vector_t< int64_t > unit_array() const
entry_type get_display(int evt_type) const
this_type & operator-=(const this_type &rhs)
static const short precision
Definition: papi_vector.hpp:73
string_t get_display() const
static const short width
Definition: papi_vector.hpp:74
typename base_type::storage_type storage_type
Definition: papi_vector.hpp:66
friend std::ostream & operator<<(std::ostream &os, const this_type &obj)