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.
components.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
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 /**
26  * \file timemory/components/craypat/components.hpp
27  * \brief Implementation of the craypat component(s)
28  */
29 
30 #pragma once
31 
33 //
34 #include "timemory/components/craypat/backends.hpp"
36 
37 //======================================================================================//
38 //
39 namespace tim
40 {
41 namespace component
42 {
43 //
44 //--------------------------------------------------------------------------------------//
45 //
46 /// \struct tim::component::craypat_record
47 /// \brief Provides scoping the CrayPAT profiler. Global initialization stops
48 /// the profiler, the first call to `start()` starts the profiler again on the
49 /// calling thread. Instance counting is enabled per-thread and each call to start
50 /// increments the counter. All calls to `stop()` have no effect until the counter reaches
51 /// zero, at which point the compiler is turned off again.
52 ///
54 : base<craypat_record, void>
55 , private policy::instance_tracker<craypat_record>
56 {
58  using value_type = void;
61 
62  static std::string label() { return "craypat_record"; }
64  {
65  return "Toggles CrayPAT recording on calling thread";
66  }
67 
68  static void global_init() { backend::craypat::record(PAT_STATE_OFF); }
69 
70  static void global_finalize() { backend::craypat::record(PAT_STATE_OFF); }
71 
72  void start()
73  {
75  if(tracker_type::m_thr == 0)
76  backend::craypat::record(PAT_STATE_ON);
77  }
78 
79  void stop()
80  {
82  if(tracker_type::m_thr == 0)
83  backend::craypat::record(PAT_STATE_OFF);
84  }
85 };
86 //
87 //--------------------------------------------------------------------------------------//
88 //
89 /// \struct tim::component::craypat_region
90 /// \brief Adds a region label to the CrayPAT profiling output
91 ///
93 : base<craypat_region, void>
94 , private policy::instance_tracker<craypat_region, false>
95 {
97 
98  static std::string label() { return "craypat_region"; }
99  static std::string description() { return "Adds region labels to CrayPAT output"; }
100 
101  void start()
102  {
104  backend::craypat::region_begin(tracker_type::m_tot, m_label.c_str());
105  }
106 
107  void stop()
108  {
109  backend::craypat::region_end(tracker_type::m_tot);
111  }
112 
113  void set_prefix(const std::string& _label) { m_label = _label; }
114 
115 private:
116  std::string m_label = {};
117 };
118 //
119 //--------------------------------------------------------------------------------------//
120 //
121 /// \struct tim::component::craypat_region
122 /// \brief Retrieves the names and value of any counter events that have been set to count
123 /// on the hardware category
124 ///
125 struct craypat_counters : base<craypat_counters, std::vector<unsigned long>>
126 {
127  using value_type = std::vector<unsigned long>;
131  using strvector_t = std::vector<std::string>;
132 
133  static std::string label() { return "craypat_counters"; }
134 
136  {
137  return "Names and value of any counter events that have been set to count on the "
138  "hardware category";
139  }
140 
141  static void configure()
142  {
143  std::set<int> _empty;
144  int _idx = 0;
145  for(auto& citr : get_persistent_data().m_categories)
146  {
147  int _category = std::get<0>(citr);
148  // temporary data
149  const char** _names = nullptr;
150  unsigned long* _values = nullptr;
151  int* _nevents = nullptr;
152  // get data from craypat
153  backend::craypat::counters(_category, _names, _values, _nevents);
154  if(_names && _values && _nevents)
155  {
156  std::get<1>(citr) = *_nevents;
157  for(int i = 0; i < *_nevents; ++i)
158  {
159  std::get<2>(citr).push_back(_names[i]);
160  get_persistent_data().m_labels.push_back(_names[i]);
161  }
162  }
163  else
164  {
165  _empty.insert(_idx);
166  }
167  ++_idx;
168  }
169 
170  get_persistent_data().m_events = get_persistent_data().m_labels.size();
171 
172  // erase the unused categories
173  for(auto ritr = _empty.rbegin(); ritr != _empty.rend(); ++ritr)
174  {
175  auto itr = get_persistent_data().m_categories.begin();
176  std::advance(itr, *ritr);
177  get_persistent_data().m_categories.erase(itr);
178  }
179  }
180 
181  static void global_init() { configure(); }
182 
184  {
185  value_type _data;
186  for(const auto& citr : get_persistent_data().m_categories)
187  {
188  int _category = std::get<0>(citr);
189  // temporary data
190  const char** _names = nullptr;
191  unsigned long* _values = nullptr;
192  int* _nevents = nullptr;
193  // get data from craypat
194  backend::craypat::counters(_category, _names, _values, _nevents);
195  if(_names && _values && _nevents)
196  {
197  // current beginning index
198  auto _off = _data.size();
199  // make sure data size is consistent
200  _data.resize(_off + std::get<1>(citr), 0);
201  // compute the size of loop
202  int _n = std::min(std::get<1>(citr), *_nevents);
203  for(int i = 0; i < _n; ++i)
204  _data[_off + i] = _values[i];
205  }
206  }
207  return _data;
208  }
209 
210  static strvector_t label_array() { return get_persistent_data().m_labels; }
211 
213  {
214  return strvector_t(get_persistent_data().m_events, "");
215  }
216 
217  static std::vector<unsigned long> unit_array()
218  {
219  return std::vector<unsigned long>(get_persistent_data().m_events, 1);
220  }
221 
223  {
224  return strvector_t(get_persistent_data().m_events, "");
225  }
226 
227  TIMEMORY_NODISCARD value_type get() const { return base_type::load(); }
228  TIMEMORY_NODISCARD value_type get_display() const { return base_type::load(); }
229 
230  void start() { value = record(); }
231 
232  void stop()
233  {
234  using namespace tim::component::operators;
235  value = (record() - value);
236  accum += value;
237  }
238 
239 private:
240  struct persistent_data
241  {
242  using category_tuple_t = std::tuple<int, int, strvector_t>;
243  using category_vector_t = std::vector<category_tuple_t>;
244  category_vector_t m_categories =
245  category_vector_t({ category_tuple_t{ PAT_CTRS_CPU, 0, strvector_t{} },
246  category_tuple_t{ PAT_CTRS_NETWORK, 0, strvector_t{} },
247  category_tuple_t{ PAT_CTRS_ACCEL, 0, strvector_t{} },
248  category_tuple_t{ PAT_CTRS_RAPL, 0, strvector_t{} },
249  category_tuple_t{ PAT_CTRS_PM, 0, strvector_t{} },
250  category_tuple_t{ PAT_CTRS_UNCORE, 0, strvector_t{} } });
251  strvector_t m_labels = {};
252  size_t m_events = 0;
253  };
254 
255  static persistent_data& get_persistent_data()
256  {
257  static persistent_data _instance;
258  return _instance;
259  }
260 };
261 //
262 //--------------------------------------------------------------------------------------//
263 //
264 /// \struct tim::component::craypat_heap_stats
265 /// \brief Dumps the craypat heap statistics
266 ///
267 struct craypat_heap_stats : base<craypat_heap_stats, void>
268 {
269  static std::string label() { return "craypat_heap_stats"; }
270  static std::string description() { return "Undocumented by 'pat_api.h'"; }
271 
272  void start() {}
273  static void stop() { backend::craypat::heap_stats(); }
274 };
275 //
276 //--------------------------------------------------------------------------------------//
277 //
278 /// \struct tim::component::craypat_flush_buffer
279 /// \brief Writes all the recorded contents in the data buffer. Returns the number of
280 /// bytes flushed
281 ///
282 struct craypat_flush_buffer : base<craypat_flush_buffer, unsigned long>
283 {
284  using value_type = unsigned long;
287 
288  static std::string label() { return "craypat_flush_buffer"; }
290  {
291  return "Writes all the recorded contents in the data buffer. Returns the number "
292  "of bytes flushed";
293  }
294 
296  {
297  unsigned long _nbytes;
298  backend::craypat::flush_buffer(&_nbytes);
299  return _nbytes;
300  }
301 
302  TIMEMORY_NODISCARD double get() const { return m_nbytes; }
303  TIMEMORY_NODISCARD auto get_display() const { return get(); }
304  void start() {}
305  void stop()
306  {
307  value = record();
308  accum += record();
309  }
310 
311 private:
312  unsigned long m_nbytes = 0;
313 };
314 //
315 } // namespace component
316 } // namespace tim
317 //
318 //======================================================================================//
Declare the craypat component types.
void record(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:616
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
tim::mpl::apply< std::string > string
Definition: macros.hpp:52
decltype(auto) load()
storage< Tp, Value > storage_type
Definition: declaration.hpp:90
std::vector< unsigned long > value_type
Definition: components.hpp:127
static strvector_t display_unit_array()
Definition: components.hpp:222
typename base_type::storage_type storage_type
Definition: components.hpp:130
value_type get_display() const
Definition: components.hpp:228
static std::vector< unsigned long > unit_array()
Definition: components.hpp:217
static strvector_t label_array()
Definition: components.hpp:210
static std::string description()
Definition: components.hpp:135
std::vector< std::string > strvector_t
Definition: components.hpp:131
static strvector_t description_array()
Definition: components.hpp:212
static std::string label()
Definition: components.hpp:133
Writes all the recorded contents in the data buffer. Returns the number of bytes flushed.
Definition: components.hpp:283
Dumps the craypat heap statistics.
Definition: components.hpp:268
static std::string description()
Definition: components.hpp:270
Provides scoping the CrayPAT profiler. Global initialization stops the profiler, the first call to st...
Definition: components.hpp:56
static std::string description()
Definition: components.hpp:63
static std::string label()
Definition: components.hpp:62
Adds a region label to the CrayPAT profiling output.
Definition: components.hpp:95
void set_prefix(const std::string &_label)
Definition: components.hpp:113
static std::string description()
Definition: components.hpp:99
static std::string label()
Definition: components.hpp:98