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.
definition.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 #pragma once
26 
30 #include "timemory/mpl/math.hpp"
31 #include "timemory/mpl/types.hpp"
34 #include "timemory/units.hpp"
35 
36 namespace tim
37 {
38 namespace component
39 {
40 //
41 //======================================================================================//
42 //
43 // NON-VOID BASE
44 //
45 //======================================================================================//
46 //
47 template <typename Tp, typename Value>
48 void
50 {
51  laps = 0;
54 }
55 //
56 //--------------------------------------------------------------------------------------//
57 //
58 template <typename Tp, typename Value>
59 void
60 base<Tp, Value>::get(void*& ptr, size_t _typeid_hash) const
61 {
62  if(!ptr && _typeid_hash == typeid_hash<Tp>())
63  ptr = reinterpret_cast<void*>(const_cast<base_type*>(this));
64 }
65 //
66 //--------------------------------------------------------------------------------------//
67 //
68 template <typename Tp, typename Value>
69 void
71 {
72  set_is_running(true);
73 }
74 //
75 //--------------------------------------------------------------------------------------//
76 //
77 template <typename Tp, typename Value>
78 void
80 {
81  if(get_is_running())
82  {
83  ++laps;
84  set_is_transient(true);
85  set_is_running(false);
86  }
87 }
88 //
89 //--------------------------------------------------------------------------------------//
90 //
91 template <typename Tp, typename Value>
92 typename base<Tp, Value>::base_storage_type*
94 {
95  return tim::base::storage::template base_instance<Tp, Value>();
96 }
97 //
98 //--------------------------------------------------------------------------------------//
99 //
100 template <typename Tp, typename Value>
101 short
103 {
104  static short _instance = Type::width;
105  if(settings::width() >= 0)
106  _instance = settings::width();
107 
108  if(timing_category_v && settings::timing_width() >= 0)
109  {
110  _instance = settings::timing_width();
111  }
112  else if(memory_category_v && settings::memory_width() >= 0)
113  {
114  _instance = settings::memory_width();
115  }
116 
117  return _instance;
118 }
119 //
120 //--------------------------------------------------------------------------------------//
121 //
122 template <typename Tp, typename Value>
123 short
125 {
126  static short _instance = Type::precision;
127  if(settings::precision() >= 0)
128  _instance = settings::precision();
129 
130  if(timing_category_v && settings::timing_precision() >= 0)
131  {
132  _instance = settings::timing_precision();
133  }
134  else if(memory_category_v && settings::memory_precision() >= 0)
135  {
136  _instance = settings::memory_precision();
137  }
138 
139  return _instance;
140 }
141 //
142 //--------------------------------------------------------------------------------------//
143 //
144 template <typename Tp, typename Value>
145 std::ios_base::fmtflags
147 {
148  static std::ios_base::fmtflags _instance = Type::format_flags;
149 
150  auto _set_scientific = []() {
151  _instance &= (std::ios_base::fixed & std::ios_base::scientific);
152  _instance |= (std::ios_base::scientific);
153  };
154 
155  if(!percent_units_v &&
156  (settings::scientific() || (timing_category_v && settings::timing_scientific()) ||
157  (memory_category_v && settings::memory_scientific())))
158  _set_scientific();
159 
160  return _instance;
161 }
162 //
163 //--------------------------------------------------------------------------------------//
164 //
165 template <typename Tp, typename Value>
168 {
169  return metadata<Tp>::label();
170 }
171 //
172 //--------------------------------------------------------------------------------------//
173 //
174 template <typename Tp, typename Value>
177 {
178  return metadata<Tp>::description();
179 }
180 //
181 //--------------------------------------------------------------------------------------//
182 //
183 template <typename Tp, typename Value>
186 {
187  static std::string _instance = Type::label();
188  return _instance;
189 }
190 //
191 //--------------------------------------------------------------------------------------//
192 //
193 template <typename Tp, typename Value>
196 {
197  static std::string _instance = Type::description();
198  return _instance;
199 }
200 //
201 //--------------------------------------------------------------------------------------//
202 //
203 // operator + - * / (Type)
204 //
205 //--------------------------------------------------------------------------------------//
206 //
207 template <typename Tp, typename Value>
208 Tp&
209 base<Tp, Value>::plus_oper(const Tp& rhs)
210 {
211  data_type::plus(rhs);
212  return static_cast<Type&>(*this);
213 }
214 //
215 //--------------------------------------------------------------------------------------//
216 //
217 template <typename Tp, typename Value>
218 Tp&
219 base<Tp, Value>::minus_oper(const Tp& rhs)
220 {
221  data_type::minus(rhs);
222  return static_cast<Type&>(*this);
223 }
224 //
225 //--------------------------------------------------------------------------------------//
226 //
227 template <typename Tp, typename Value>
228 Tp&
229 base<Tp, Value>::multiply_oper(const Tp& rhs)
230 {
231  data_type::multiply(rhs);
232  return static_cast<Type&>(*this);
233 }
234 //
235 //--------------------------------------------------------------------------------------//
236 //
237 template <typename Tp, typename Value>
238 Tp&
239 base<Tp, Value>::divide_oper(const Tp& rhs)
240 {
241  data_type::divide(rhs);
242  return static_cast<Type&>(*this);
243 }
244 //
245 //--------------------------------------------------------------------------------------//
246 //
247 // operator + - * / (Value)
248 //
249 //--------------------------------------------------------------------------------------//
250 //
251 template <typename Tp, typename Value>
252 Tp&
253 base<Tp, Value>::plus_oper(const Value& rhs)
254 {
255  data_type::plus(rhs);
256  return static_cast<Type&>(*this);
257 }
258 //
259 //--------------------------------------------------------------------------------------//
260 //
261 template <typename Tp, typename Value>
262 Tp&
263 base<Tp, Value>::minus_oper(const Value& rhs)
264 {
265  data_type::minus(rhs);
266  return static_cast<Type&>(*this);
267 }
268 //
269 //--------------------------------------------------------------------------------------//
270 //
271 template <typename Tp, typename Value>
272 Tp&
273 base<Tp, Value>::multiply_oper(const Value& rhs)
274 {
275  data_type::minus(rhs);
276  return static_cast<Type&>(*this);
277 }
278 //
279 //--------------------------------------------------------------------------------------//
280 //
281 template <typename Tp, typename Value>
282 Tp&
283 base<Tp, Value>::divide_oper(const Value& rhs)
284 {
285  data_type::divide(rhs);
286  return static_cast<Type&>(*this);
287 }
288 //
289 //--------------------------------------------------------------------------------------//
290 //
291 // operator + - * / <<
292 //
293 //--------------------------------------------------------------------------------------//
294 //
295 template <typename Tp, typename Value>
296 Tp
298 {
299  return Tp(static_cast<const Tp&>(lhs)) += static_cast<const Tp&>(rhs);
300 }
301 //
302 //--------------------------------------------------------------------------------------//
303 //
304 template <typename Tp, typename Value>
305 Tp
307 {
308  return Tp(static_cast<const Tp&>(lhs)) -= static_cast<const Tp&>(rhs);
309 }
310 //
311 //--------------------------------------------------------------------------------------//
312 //
313 template <typename Tp, typename Value>
314 Tp operator*(const base<Tp, Value>& lhs, const base<Tp, Value>& rhs)
315 {
316  return Tp(static_cast<const Tp&>(lhs)) *= static_cast<const Tp&>(rhs);
317 }
318 //
319 //--------------------------------------------------------------------------------------//
320 //
321 template <typename Tp, typename Value>
322 Tp
324 {
325  return Tp(static_cast<const Tp&>(lhs)) /= static_cast<const Tp&>(rhs);
326 }
327 //
328 //======================================================================================//
329 //
330 // VOID BASE
331 //
332 //======================================================================================//
333 //
334 template <typename Tp>
335 void
337 {
339 }
340 //
341 //--------------------------------------------------------------------------------------//
342 //
343 template <typename Tp>
344 void
346 {
347  set_is_running(true);
348 }
349 //
350 //--------------------------------------------------------------------------------------//
351 //
352 template <typename Tp>
353 void
355 {
356  if(get_is_running())
357  set_is_transient(true);
358  set_is_running(false);
359 }
360 //
361 //--------------------------------------------------------------------------------------//
362 //
363 template <typename Tp>
364 void
365 base<Tp, void>::get(void*& ptr, size_t _typeid_hash) const
366 {
367  if(!ptr && _typeid_hash == typeid_hash<Tp>())
368  ptr = reinterpret_cast<void*>(const_cast<base_type*>(this));
369 }
370 //
371 //--------------------------------------------------------------------------------------//
372 //
373 template <typename Tp>
376 {
377  return metadata<Tp>::label();
378 }
379 //
380 //--------------------------------------------------------------------------------------//
381 //
382 template <typename Tp>
385 {
386  return metadata<Tp>::description();
387 }
388 //
389 //--------------------------------------------------------------------------------------//
390 //
391 template <typename Tp>
394 {
395  static std::string _instance = Type::label();
396  return _instance;
397 }
398 //
399 //--------------------------------------------------------------------------------------//
400 //
401 template <typename Tp>
404 {
405  static std::string _instance = Type::description();
406  return _instance;
407 }
408 //
409 //--------------------------------------------------------------------------------------//
410 //
411 } // namespace component
412 } // namespace tim
413 
419 
420 namespace tim
421 {
422 namespace component
423 {
424 //
425 template <typename Tp, typename Value>
426 opaque
427 base<Tp, Value>::get_opaque(scope::config _scope)
428 {
429  auto _typeid_hash = typeid_hash<Tp>();
430 
431  opaque _obj{};
432 
433  _obj.m_valid = true;
434 
435  _obj.m_typeid = _typeid_hash;
436 
437  _obj.m_setup = [](void* v_result, const string_view_t& _prefix,
438  scope::config arg_scope) {
439  DEBUG_PRINT_HERE("Setting up %s", demangle<Tp>().c_str());
440  Tp* _result = static_cast<Tp*>(v_result);
441  if(!_result)
442  _result = new Tp{};
443  invoke::set_prefix<TIMEMORY_API>(std::tie(*_result), _prefix);
444  invoke::set_scope<TIMEMORY_API>(std::tie(*_result), arg_scope);
445  return (void*) _result;
446  };
447 
448  _obj.m_push = [_scope](void*& v_result, const string_view_t& _prefix,
449  scope::config arg_scope) {
450  if(v_result)
451  {
452  DEBUG_PRINT_HERE("Pushing %s", demangle<Tp>().c_str());
453  auto _hash = add_hash_id(_prefix);
454  Tp* _result = static_cast<Tp*>(v_result);
455  invoke::push<TIMEMORY_API>(std::tie(*_result), _scope + arg_scope, _hash);
456  }
457  };
458 
459  _obj.m_sample = [](void* v_result) {
460  if(v_result)
461  {
462  DEBUG_PRINT_HERE("Sampling %s", demangle<Tp>().c_str());
463  Tp* _result = static_cast<Tp*>(v_result);
464  invoke::invoke<operation::sample, TIMEMORY_API>(std::tie(*_result));
465  }
466  };
467 
468  _obj.m_start = [](void* v_result) {
469  if(v_result)
470  {
471  DEBUG_PRINT_HERE("Starting %s", demangle<Tp>().c_str());
472  Tp* _result = static_cast<Tp*>(v_result);
473  invoke::start<TIMEMORY_API>(std::tie(*_result));
474  }
475  };
476 
477  _obj.m_stop = [](void* v_result) {
478  if(v_result)
479  {
480  DEBUG_PRINT_HERE("Stopping %s", demangle<Tp>().c_str());
481  Tp* _result = static_cast<Tp*>(v_result);
482  invoke::stop<TIMEMORY_API>(std::tie(*_result));
483  }
484  };
485 
486  _obj.m_pop = [](void* v_result) {
487  if(v_result)
488  {
489  DEBUG_PRINT_HERE("Popping %s", demangle<Tp>().c_str());
490  Tp* _result = static_cast<Tp*>(v_result);
491  invoke::pop<TIMEMORY_API>(std::tie(*_result));
492  }
493  };
494 
495  _obj.m_get = [_typeid_hash](void* v_result, void*& _ptr, size_t _hash) {
496  if(_hash == _typeid_hash && v_result && !_ptr)
497  {
498  DEBUG_PRINT_HERE("Getting %s", demangle<Tp>().c_str());
499  Tp* _result = static_cast<Tp*>(v_result);
500  // invoke::get<TIMEMORY_API>(std::tie(*_result), _ptr, _hash);
501  // operation::get<Tp>{ *_result, _ptr, _hash };
502  invoke::invoke<operation::get, TIMEMORY_API>(std::tie(*_result), _ptr, _hash);
503  }
504  };
505 
506  _obj.m_del = [](void* v_result) {
507  if(v_result)
508  {
509  DEBUG_PRINT_HERE("Deleting %s", demangle<Tp>().c_str());
510  Tp* _result = static_cast<Tp*>(v_result);
511  delete _result;
512  }
513  };
514 
515  return _obj;
516 }
517 //
518 template <typename Tp>
519 opaque
520 base<Tp, void>::get_opaque(scope::config _scope)
521 {
522  auto _typeid_hash = typeid_hash<Tp>();
523 
524  opaque _obj{};
525 
526  _obj.m_valid = true;
527 
528  _obj.m_typeid = _typeid_hash;
529 
530  _obj.m_setup = [](void* v_result, const string_view_t& _prefix,
531  scope::config arg_scope) {
532  DEBUG_PRINT_HERE("Setting up %s", demangle<Tp>().c_str());
533  Tp* _result = static_cast<Tp*>(v_result);
534  if(!_result)
535  _result = new Tp{};
536  invoke::set_prefix<TIMEMORY_API>(std::tie(*_result), _prefix);
537  invoke::set_scope<TIMEMORY_API>(std::tie(*_result), arg_scope);
538  return (void*) _result;
539  };
540 
541  _obj.m_push = [_scope](void*& v_result, const string_view_t& _prefix,
542  scope::config arg_scope) {
543  if(v_result)
544  {
545  DEBUG_PRINT_HERE("Pushing %s", demangle<Tp>().c_str());
546  auto _hash = add_hash_id(_prefix);
547  Tp* _result = static_cast<Tp*>(v_result);
548  invoke::push<TIMEMORY_API>(std::tie(*_result), _scope + arg_scope, _hash);
549  }
550  };
551 
552  _obj.m_sample = [](void* v_result) {
553  if(v_result)
554  {
555  DEBUG_PRINT_HERE("Sampling %s", demangle<Tp>().c_str());
556  Tp* _result = static_cast<Tp*>(v_result);
557  invoke::invoke<operation::sample, TIMEMORY_API>(std::tie(*_result));
558  }
559  };
560 
561  _obj.m_start = [](void* v_result) {
562  if(v_result)
563  {
564  DEBUG_PRINT_HERE("Starting %s", demangle<Tp>().c_str());
565  Tp* _result = static_cast<Tp*>(v_result);
566  invoke::start<TIMEMORY_API>(std::tie(*_result));
567  }
568  };
569 
570  _obj.m_stop = [](void* v_result) {
571  if(v_result)
572  {
573  DEBUG_PRINT_HERE("Stopping %s", demangle<Tp>().c_str());
574  Tp* _result = static_cast<Tp*>(v_result);
575  invoke::stop<TIMEMORY_API>(std::tie(*_result));
576  }
577  };
578 
579  _obj.m_pop = [](void* v_result) {
580  if(v_result)
581  {
582  DEBUG_PRINT_HERE("Popping %s", demangle<Tp>().c_str());
583  Tp* _result = static_cast<Tp*>(v_result);
584  invoke::pop<TIMEMORY_API>(std::tie(*_result));
585  }
586  };
587 
588  _obj.m_get = [_typeid_hash](void* v_result, void*& _ptr, size_t _hash) {
589  if(_hash == _typeid_hash && v_result && !_ptr)
590  {
591  DEBUG_PRINT_HERE("Getting %s", demangle<Tp>().c_str());
592  Tp* _result = static_cast<Tp*>(v_result);
593  invoke::invoke<operation::get, TIMEMORY_API>(std::tie(*_result), _ptr, _hash);
594  }
595  };
596 
597  _obj.m_del = [](void* v_result) {
598  if(v_result)
599  {
600  DEBUG_PRINT_HERE("Deleting %s", demangle<Tp>().c_str());
601  Tp* _result = static_cast<Tp*>(v_result);
602  delete _result;
603  }
604  };
605 
606  return _obj;
607 }
608 //
609 } // namespace component
610 } // namespace tim
Declare the base component types.
Definition for various functions for get in operations.
Tp operator*(const base< Tp, Value > &lhs, const base< Tp, Value > &rhs)
Definition: definition.hpp:314
Tp operator+(const base< Tp, Value > &lhs, const base< Tp, Value > &rhs)
Definition: definition.hpp:297
Tp operator/(const base< Tp, Value > &lhs, const base< Tp, Value > &rhs)
Definition: definition.hpp:323
Tp operator-(const base< Tp, Value > &lhs, const base< Tp, Value > &rhs)
Definition: definition.hpp:306
void reset(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:581
Tp & divide(Tp &, const Up &)
Definition: math.hpp:858
Tp & plus(Tp &, const Up &)
Definition: math.hpp:565
Tp & minus(Tp &, const Up &)
Definition: math.hpp:633
Tp & multiply(Tp &, const Up &)
Definition: math.hpp:746
Definition: kokkosp.cpp:38
timing_precision
Definition: settings.cpp:1341
char const std::string & _prefix
Definition: definition.hpp:59
std::string string_view_t
Definition: language.hpp:100
memory_scientific
Definition: settings.cpp:1353
timing_width
Definition: settings.cpp:1343
scientific
Definition: settings.cpp:1340
tim::mpl::apply< std::string > string
Definition: macros.hpp:52
hash_value_t add_hash_id(hash_map_ptr_t &_hash_map, const string_view_t &_prefix)
add an string to the given hash-map (if it doesn't already exist) and return the hash
Definition: types.hpp:187
precision
Definition: settings.cpp:1337
memory_precision
Definition: settings.cpp:1348
memory_width
Definition: settings.cpp:1350
description("A generic option for any setting. Each argument MUST be passed in " "form: 'NAME=VALUE'. E.g. --timemory-args " "\"papi_events=PAPI_TOT_INS,PAPI_TOT_CYC\" text_output=off") .action([&](parser_t &p)
Definition: definition.hpp:334
timing_scientific
Definition: settings.cpp:1346
Declare the operations types.
Definition for various functions for sample in operations.
The declaration for the types for settings without definitions.
Declare the storage types.
static short get_precision()
Type & minus_oper(const Type &rhs)
static base_storage_type * get_storage()
void reset()
reset the values
static std::string get_label()
Type & multiply_oper(const Type &rhs)
Type & plus_oper(const Type &rhs)
void set_stopped()
store that stop has been called
static short get_width()
static fmtflags get_format_flags()
static opaque get_opaque(scope::config)
get the opaque binding for user-bundle
static std::string label()
Type & divide_oper(const Type &rhs)
auto get() const
retrieve the current measurement value in the units for the type
void set_started()
store that start has been called
static std::string get_description()
static std::string description()
static std::string label()
Definition: metadata.hpp:68
static std::string description()
Definition: metadata.hpp:77
#define DEBUG_PRINT_HERE(...)
Definition: macros.hpp:163