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.
policy.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/mpl/types.hpp"
29 #include "timemory/tpls/cereal/archives.hpp"
30 
31 #include <atomic>
32 #include <iosfwd>
33 #include <memory>
34 #include <tuple>
35 
36 namespace tim
37 {
38 //
39 template <typename Tp>
40 struct statistics;
41 //
42 namespace policy
43 {
44 //======================================================================================//
45 
46 template <typename CompT, typename Tp>
48 {
49  using type = Tp;
53 
54  static void apply(statistics<type>&, const CompT&);
55  static void apply(type&, const CompT&) {}
56 };
57 
58 //--------------------------------------------------------------------------------------//
59 //
60 template <typename CompT>
61 struct record_statistics<CompT, void>
62 {
63  using type = void;
67 
68  template <typename... ArgsT>
69  static void apply(ArgsT&&...)
70  {}
71 };
72 
73 //--------------------------------------------------------------------------------------//
74 //
75 template <typename CompT>
76 struct record_statistics<CompT, std::tuple<>>
77 {
78  using type = std::tuple<>;
79  using this_type = record_statistics<CompT, type>;
80  using policy_type = this_type;
82 
83  template <typename... ArgsT>
84  static void apply(ArgsT&&...)
85  {}
86 };
87 
88 //======================================================================================//
89 
90 template <typename Archive, typename Api>
92 {
93  using type = Archive;
94  using pointer = std::shared_ptr<type>;
95 
96  static pointer get(std::istream& is) { return std::make_shared<type>(is); }
97 };
98 
99 //--------------------------------------------------------------------------------------//
100 
101 template <typename Api>
102 struct input_archive<cereal::JSONInputArchive, Api>
103 {
104  using type = cereal::JSONInputArchive;
105  using pointer = std::shared_ptr<type>;
106 
107  static pointer get(std::istream& is) { return std::make_shared<type>(is); }
108 };
109 
110 //--------------------------------------------------------------------------------------//
111 
112 template <typename Api>
113 struct input_archive<cereal::PrettyJSONOutputArchive, Api>
114 {
115  using type = cereal::JSONInputArchive;
116  using pointer = std::shared_ptr<type>;
117 
118  static pointer get(std::istream& is) { return std::make_shared<type>(is); }
119 };
120 
121 //--------------------------------------------------------------------------------------//
122 
123 template <typename Api>
124 struct input_archive<cereal::MinimalJSONOutputArchive, Api>
125 {
126  using type = cereal::JSONInputArchive;
127  using pointer = std::shared_ptr<type>;
128 
129  static pointer get(std::istream& is) { return std::make_shared<type>(is); }
130 };
131 
132 //======================================================================================//
133 
134 template <typename Archive, typename Api>
136 {
137  using type = Archive;
138  using pointer = std::shared_ptr<type>;
139 
140  static pointer get(std::ostream& os) { return std::make_shared<type>(os); }
141 };
142 
143 //--------------------------------------------------------------------------------------//
144 
145 template <typename Api>
146 struct output_archive<cereal::PrettyJSONOutputArchive, Api>
147 {
148  using type = cereal::PrettyJSONOutputArchive;
149  using pointer = std::shared_ptr<type>;
150  using option_type = typename type::Options;
151  using indent_type = typename option_type::IndentChar;
152 
153  static unsigned int& precision()
154  {
155  static unsigned int value = 16;
156  return value;
157  }
158 
159  static unsigned int& indent_length()
160  {
161  static unsigned int value = 1;
162  return value;
163  }
164 
166  {
167  static indent_type value = indent_type::space;
168  return value;
169  }
170 
171  static pointer get(std::ostream& os)
172  {
173  // Option args: precision, spacing, indent size
174  option_type opts(precision(), indent_char(), indent_length());
175  return std::make_shared<type>(os, opts);
176  }
177 };
178 
179 //--------------------------------------------------------------------------------------//
180 ///
181 /// partial specialization for MinimalJSONOutputArchive
182 ///
183 template <typename Api>
184 struct output_archive<cereal::MinimalJSONOutputArchive, Api>
185 {
186  using type = cereal::MinimalJSONOutputArchive;
187  using pointer = std::shared_ptr<type>;
188  using option_type = typename type::Options;
189  using indent_type = typename option_type::IndentChar;
190 
191  static unsigned int& precision()
192  {
193  static unsigned int value = 16;
194  return value;
195  }
196  static unsigned int& indent_length()
197  {
198  static unsigned int value = 0;
199  return value;
200  }
202  {
203  static indent_type value = indent_type::space;
204  return value;
205  }
206 
207  static pointer get(std::ostream& os)
208  {
209  // Option args: precision, spacing, indent size
210  // The last two options are meaningless for the minimal writer
211  option_type opts(precision(), indent_char(), indent_length());
212  return std::make_shared<type>(os, opts);
213  }
214 };
215 
216 //--------------------------------------------------------------------------------------//
217 #if defined(TIMEMORY_USE_XML)
218 ///
219 /// partial specialization for XMLOutputArchive
220 ///
221 template <typename Api>
222 struct output_archive<cereal::XMLOutputArchive, Api>
223 {
224  using type = cereal::XMLOutputArchive;
225  using pointer = std::shared_ptr<type>;
226  using option_type = typename type::Options;
227  using indent_type = bool;
228  using output_type = bool;
229 
230  static unsigned int& precision()
231  {
232  static unsigned int value = 16;
233  return value;
234  }
235 
236  // indent the output
237  static indent_type& indent()
238  {
239  static indent_type value =
240  trait::pretty_archive<Api>::value || trait::pretty_archive<void>::value;
241  return value;
242  }
243 
244  // output the type as an attribute
245  static output_type& type_attribute()
246  {
247  static output_type value = false;
248  return value;
249  }
250 
251  // Whether dynamically sized containers output the size=dynamic attribute
252  static output_type& size_attribute()
253  {
254  static output_type value = false;
255  return value;
256  }
257 
258  static pointer get(std::ostream& os)
259  {
260  // Option args: precision, spacing, indent size
261  // The last two options are meaningless for the minimal writer
262  option_type opts(precision(), indent(), type_attribute(), size_attribute());
263  return std::make_shared<type>(os, opts);
264  }
265 };
266 #endif
267 //======================================================================================//
268 
269 template <typename Tp>
270 struct instance_tracker<Tp, true>
271 {
272 public:
273  using type = Tp;
274  using int_type = int64_t;
275  using pair_type = std::pair<int_type, int_type>;
276  static constexpr bool thread_support = true;
277 
278  TIMEMORY_DEFAULT_OBJECT(instance_tracker)
279 
280  enum
281  {
282  global_count = 0,
283  thread_count
284  };
285 
286 public:
287  //----------------------------------------------------------------------------------//
288  //
289  static int_type get_started_count() { return get_started().load(); }
290 
291  //----------------------------------------------------------------------------------//
292  //
293  static int_type get_thread_started_count() { return get_thread_started(); }
294 
295 protected:
296  //----------------------------------------------------------------------------------//
297  //
298  static std::atomic<int_type>& get_started()
299  {
300  static std::atomic<int_type> _instance(0);
301  return _instance;
302  }
303 
304  //----------------------------------------------------------------------------------//
305  //
307  {
308  static thread_local int_type _instance = 0;
309  return _instance;
310  }
311 
312  //----------------------------------------------------------------------------------//
313  //
314  auto start()
315  {
316  m_tot = get_started()++;
317  m_thr = get_thread_started()++;
318  return pair_type{ m_tot, m_thr };
319  }
320 
321  auto stop()
322  {
323  m_tot = --get_started();
324  m_thr = --get_thread_started();
325  return pair_type{ m_tot, m_thr };
326  }
327 
328  //----------------------------------------------------------------------------------//
329  // increment/decrement global and thread counts and return global count
330  template <size_t Idx>
332  {
333  m_tot = get_started()++;
334  m_thr = get_thread_started()++;
335  return m_tot;
336  }
337 
338  template <size_t Idx>
340  {
341  m_tot = --get_started();
342  m_thr = --get_thread_started();
343  return m_tot;
344  }
345 
346  //----------------------------------------------------------------------------------//
347  // increment/decrement global and thread counts and return thread count
348  template <size_t Idx>
350  {
351  m_tot = get_started()++;
352  m_thr = get_thread_started()++;
353  return m_thr;
354  }
355 
356  template <size_t Idx>
358  {
359  m_tot = --get_started();
360  m_thr = --get_thread_started();
361  return m_thr;
362  }
363 
364  auto get_global_count() { return m_tot; }
365  auto get_thread_count() { return m_tot; }
366 
367  auto global_tracker_start() { return (start(), m_tot); }
368  auto global_tracker_stop() { return (stop(), m_tot); }
369  auto thread_tracker_start() { return (start(), m_thr); }
370  auto thread_tracker_stop() { return (stop(), m_thr); }
371 
372 protected:
373  int_type m_tot = get_started_count();
374  int_type m_thr = get_thread_started_count();
375 };
376 
377 //======================================================================================//
378 
379 template <typename Tp>
380 struct instance_tracker<Tp, false>
381 {
382 public:
383  using type = Tp;
384  using int_type = int64_t;
385  static constexpr bool thread_support = false;
386 
387  instance_tracker() = default;
388  ~instance_tracker() = default;
390  instance_tracker(instance_tracker&&) noexcept = default;
391  instance_tracker& operator=(const instance_tracker&) = default;
392  instance_tracker& operator=(instance_tracker&&) noexcept = default;
393 
394 public:
395  //----------------------------------------------------------------------------------//
396  //
397  static int_type get_started_count() { return get_started().load(); }
398 
399 protected:
400  //----------------------------------------------------------------------------------//
401  //
402  static std::atomic<int_type>& get_started()
403  {
404  static std::atomic<int_type> _instance(0);
405  return _instance;
406  }
407 
408  //----------------------------------------------------------------------------------//
409  //
410  auto start()
411  {
412  m_tot = get_started()++;
413  return m_tot;
414  }
415 
416  //----------------------------------------------------------------------------------//
417  //
418  auto stop()
419  {
420  m_tot = --get_started();
421  return m_tot;
422  }
423 
424  auto get_global_count() { return m_tot; }
425  auto global_tracker_start() { return (start(), m_tot); }
426  auto global_tracker_stop() { return (stop(), m_tot); }
427 
428 protected:
429  int_type m_tot = get_started_count();
430 };
431 
432 //======================================================================================//
433 
434 } // namespace policy
435 } // namespace tim
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
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
precision
Definition: settings.cpp:1337
Provides a static get() function which returns a shared pointer to an instance of the given archive f...
Definition: policy.hpp:92
static pointer get(std::istream &is)
Definition: policy.hpp:96
std::shared_ptr< type > pointer
Definition: policy.hpp:94
static std::atomic< int_type > & get_started()
Definition: policy.hpp:402
instance_tracker(const instance_tracker &)=default
instance_tracker(instance_tracker &&) noexcept=default
enable_if_t< Idx==thread_count, int_type > start()
Definition: policy.hpp:349
static int_type get_thread_started_count()
Definition: policy.hpp:293
static std::atomic< int_type > & get_started()
Definition: policy.hpp:298
enable_if_t< Idx==global_count, int_type > start()
Definition: policy.hpp:331
enable_if_t< Idx==thread_count, int_type > stop()
Definition: policy.hpp:357
static int_type & get_thread_started()
Definition: policy.hpp:306
enable_if_t< Idx==global_count, int_type > stop()
Definition: policy.hpp:339
std::pair< int_type, int_type > pair_type
Definition: policy.hpp:275
Provides a static get() function which return a shared pointer to an instance of the given archive fo...
Definition: policy.hpp:136
std::shared_ptr< type > pointer
Definition: policy.hpp:138
static pointer get(std::ostream &os)
Definition: policy.hpp:140
Specification of how to accumulate statistics. This will not be used unless tim::trait::statistics ha...
Definition: policy.hpp:48
statistics< type > statistics_type
Definition: policy.hpp:52
static void apply(type &, const CompT &)
Definition: policy.hpp:55
static void apply(statistics< type > &, const CompT &)
record_statistics< CompT, type > this_type
Definition: policy.hpp:50
A generic class for statistical accumulation. It uses the timemory math overloads to enable statistic...
Definition: statistics.hpp:74