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.
declaration.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/**
26 * \file timemory/operations/declaration.hpp
27 * \brief The declaration for the types for operations without definitions
28 */
29
30#pragma once
31
32#include "timemory/enum.h"
38
39#include <algorithm>
40#include <bitset>
41#include <cstdio>
42#include <iostream>
43#include <map>
44#include <ostream>
45#include <set>
46#include <sstream>
47#include <string>
48#include <tuple>
49#include <type_traits>
50#include <vector>
51
52//
53//--------------------------------------------------------------------------------------//
54//
55#if !defined(SFINAE_WARNING)
56# if defined(DEBUG)
57# define SFINAE_WARNING(TYPE) \
58 if(::tim::trait::is_available<TYPE>::value) \
59 { \
60 static bool _once = false; \
61 if(!_once) \
62 { \
63 _once = true; \
64 fprintf(stderr, "[%s@%s:%i]> Warning! SFINAE disabled for %s\n", \
65 __FUNCTION__, __FILE__, __LINE__, \
66 ::tim::demangle<TYPE>().c_str()); \
67 } \
68 }
69# else
70# define SFINAE_WARNING(...)
71# endif
72#endif
73//
74//--------------------------------------------------------------------------------------//
75//
76
77namespace tim
78{
79//
80namespace component
81{
82struct empty_storage;
83}
84//
85//--------------------------------------------------------------------------------------//
86//
87///
88/// \struct storage_initializer
89/// \brief This provides an object that can initialize the storage opaquely, e.g.
90/// \code{.cpp}
91/// namespace
92/// {
93/// tim::storage_initializer storage = tim::storage_initalizer::get<T>();
94/// }
95/// \endcode
96///
98{
99 TIMEMORY_DEFAULT_OBJECT(storage_initializer)
100
101 template <typename T>
103 std::true_type) TIMEMORY_VISIBILITY("default");
104
105 template <typename T>
107 std::false_type) TIMEMORY_VISIBILITY("default");
108
109 template <typename T>
110 static storage_initializer get() TIMEMORY_VISIBILITY("default");
111
112 template <size_t Idx, enable_if_t<Idx != TIMEMORY_COMPONENTS_END> = 0>
113 static storage_initializer get() TIMEMORY_VISIBILITY("default");
114
115 template <size_t Idx, enable_if_t<Idx == TIMEMORY_COMPONENTS_END> = 0>
116 static auto get() TIMEMORY_VISIBILITY("default");
117
118 template <typename... Tp, enable_if_t<sizeof...(Tp) != 1> = 0>
119 static auto get() TIMEMORY_VISIBILITY("default");
120
121 template <size_t... Idx, enable_if_t<sizeof...(Idx) != 1> = 0>
122 static auto get() TIMEMORY_VISIBILITY("default");
123
124 template <size_t... Idx>
125 static auto get(std::index_sequence<Idx...>) TIMEMORY_VISIBILITY("default");
126};
127//
128//--------------------------------------------------------------------------------------//
129//
130template <typename T>
133{
134 return get<T>(trait::is_available_t<T>{});
135}
136//
137//--------------------------------------------------------------------------------------//
138//
139template <size_t Idx, enable_if_t<Idx == TIMEMORY_COMPONENTS_END>>
140auto
142{
143 return get(std::make_index_sequence<Idx>{});
144}
145//
146//--------------------------------------------------------------------------------------//
147//
148template <typename... Tp, enable_if_t<sizeof...(Tp) != 1>>
149auto
151{
152 return TIMEMORY_RETURN_FOLD_EXPRESSION(storage_initializer::get<Tp>());
153}
154//
155//--------------------------------------------------------------------------------------//
156//
157template <size_t... Idx, enable_if_t<sizeof...(Idx) != 1>>
158auto
160{
161 return TIMEMORY_RETURN_FOLD_EXPRESSION(storage_initializer::get<Idx>());
162}
163//
164//--------------------------------------------------------------------------------------//
165//
166template <size_t... Idx>
167auto storage_initializer::get(std::index_sequence<Idx...>)
168{
169 return TIMEMORY_RETURN_FOLD_EXPRESSION(storage_initializer::get<Idx>());
170}
171//
172//--------------------------------------------------------------------------------------//
173//
174namespace operation
175{
176//
177//--------------------------------------------------------------------------------------//
178//
179//
180//
181//--------------------------------------------------------------------------------------//
182//
184{};
185//
186//--------------------------------------------------------------------------------------//
187//
188/// \struct common_utils
189/// \brief common string manipulation utilities
190///
191//
192//--------------------------------------------------------------------------------------//
193//
195{
196 using attributes_t = std::map<string_t, string_t>;
197 using strset_t = std::set<string_t>;
198 using stringstream_t = std::stringstream;
199 using strvec_t = std::vector<string_t>;
200
201public:
202 template <typename Head, typename... Tail>
203 static constexpr bool not_string(enable_if_t<sizeof...(Tail) == 0, int> = 0)
204 {
205 return !std::is_same<decay_t<Head>, std::string>::value;
206 }
207
208 template <typename Head, typename... Tail>
209 static constexpr bool not_string(enable_if_t<sizeof...(Tail) != 0, int> = 0)
210 {
211 return !std::is_same<decay_t<Head>, std::string>::value && not_string<Tail...>();
212 }
213
214 template <typename Head, typename... Tail>
215 static constexpr bool is_string(enable_if_t<sizeof...(Tail) == 0, int> = 0)
216 {
217 return std::is_same<decay_t<Head>, std::string>::value;
218 }
219
220 template <typename Head, typename... Tail>
221 static constexpr bool is_string(enable_if_t<sizeof...(Tail) != 0, int> = 0)
222 {
223 return std::is_same<decay_t<Head>, std::string>::value && is_string<Tail...>();
224 }
225
226public:
227 template <typename Tp>
228 static size_t get_distance(const Tp& _data)
229 {
230 return get_distance_sfinae(_data);
231 }
232
233private:
234 template <typename Tp>
235 static auto get_distance_sfinae(const Tp& _data, int)
236 -> decltype(std::distance(_data.begin(), _data.end()), size_t())
237 {
238 return std::distance(_data.begin(), _data.end());
239 }
240
241 template <typename Tp>
242 static auto get_distance_sfinae(const Tp&, long) -> size_t
243 {
244 return size_t(1);
245 }
246
247 template <typename Tp>
248 static auto get_distance_sfinae(const Tp& _data)
249 -> decltype(get_distance_sfinae(_data, 0))
250 {
251 return get_distance_sfinae(_data, 0);
252 }
253
254public:
255 template <typename Tp, enable_if_t<std::is_arithmetic<Tp>::value, int> = 0>
256 static Tp get_entry(const Tp& _data, size_t)
257 {
258 return _data;
259 }
260
261 template <typename Tp, enable_if_t<!std::is_arithmetic<Tp>::value, int> = 0>
262 static auto get_entry(const Tp& _data, size_t _idx)
263 -> decltype(get_entry_sfinae_(_data, _idx))
264 {
265 return get_entry_sfinae_<Tp>(_data, _idx);
266 }
267
268 template <typename Tp, size_t Idx>
269 static Tp get_entry(const Tp& _data, size_t)
270 {
271 return _data;
272 }
273
274private:
275 template <typename Tp>
276 static auto get_entry_sfinae(const Tp& _data, int, size_t _idx)
277 -> decltype(_data.begin(), typename Tp::value_type())
278 {
279 auto sz = std::distance(_data.begin(), _data.end());
280 auto n = _idx % sz;
281 auto itr = _data.begin();
282 std::advance(itr, n);
283 return *itr;
284 }
285
286 template <typename Tp>
287 static Tp get_entry_sfinae(const Tp& _data, long, size_t)
288 {
289 return _data;
290 }
291
292 template <typename Tp>
293 static auto get_entry_sfinae_(const Tp& _data, size_t _idx)
294 -> decltype(get_entry_sfinae(_data, 0, _idx))
295 {
296 return get_entry_sfinae<Tp>(_data, 0, _idx);
297 }
298
299public:
300 template <typename Tp, typename Wp, typename Pp>
301 static void write(std::vector<std::stringstream*>& _os,
302 std::ios_base::fmtflags _format, const Tp& _data, const Wp& _width,
303 const Pp& _prec)
304 {
305 size_t num_data = get_distance(_data);
306
307 for(size_t i = 0; i < num_data; ++i)
308 {
309 auto _idata = get_entry<Tp>(_data, i);
310 auto _iwidth = get_entry<Wp>(_width, i);
311 auto _iprec = get_entry<Pp>(_prec, i);
312 auto* ss = new std::stringstream;
313 ss->setf(_format);
314 (*ss) << std::setw(_iwidth) << std::setprecision(_iprec) << _idata;
315 _os.emplace_back(ss);
316 }
317 }
318
319 template <typename... Tp, size_t... Idx, typename Wp, typename Pp>
320 static void write(std::vector<std::stringstream*>& _os,
321 std::ios_base::fmtflags _format, const std::tuple<Tp...>& _data,
322 const Wp& _width, const Pp& _prec, index_sequence<Idx...>)
323 {
325 write(_os, _format, std::get<Idx>(_data), _width, _prec));
326 }
327
328 template <typename... Tp, typename Wp, typename Pp>
329 static void write(std::vector<std::stringstream*>& _os,
330 std::ios_base::fmtflags _format, const std::tuple<Tp...>& _data,
331 const Wp& _width, const Pp& _prec)
332 {
333 constexpr size_t N = sizeof...(Tp);
334 write(_os, _format, _data, _width, _prec, make_index_sequence<N>{});
335 }
336
337public:
338 template <typename Tp>
339 static int64_t get_labels_size(const Tp& _data)
340 {
341 return get_labels_size_sfinae(_data, 0);
342 }
343
344private:
345 template <typename Tp>
346 static auto get_labels_size_sfinae(const Tp& _data, int)
347 -> decltype((void) _data.label_array(), int64_t())
348 {
349 return _data.label_array().size();
350 }
351
352 template <typename Tp>
353 static auto get_labels_size_sfinae(const Tp&, long) -> int64_t
354 {
355 return 1;
356 }
357
358public:
359 template <typename Tp>
360 static strvec_t get_labels(const Tp& _data)
361 {
362 return get_labels_sfinae(_data, 0, 0);
363 }
364
365private:
366 template <typename Tp>
367 static auto get_labels_sfinae(const Tp& _data, int, int)
368 -> decltype((void) _data.label_array(), strvec_t{})
369 {
371 for(const auto& itr : _data.label_array())
372 _ret.push_back(itr);
373 return _ret;
374 }
375
376 template <typename Tp>
377 static auto get_labels_sfinae(const Tp& _data, int, long)
378 -> decltype((void) _data.get_label(), strvec_t{})
379 {
380 return strvec_t{ _data.get_label() };
381 }
382
383 template <typename Tp>
384 static auto get_labels_sfinae(const Tp&, long, long) -> strvec_t
385 {
386 return strvec_t{ "" };
387 }
388
389public:
390 template <typename T>
391 static strvec_t as_string_vec(const T& _data)
392 {
393 return strvec_t{ _data };
394 }
395
396 template <typename Tp>
397 static std::string as_string(const Tp& _obj)
398 {
399 std::stringstream ss;
400 ss << _obj;
401 return ss.str();
402 }
403
404 template <typename... T, size_t... Idx>
405 static strvec_t as_string_vec(const std::tuple<T...>& _obj, index_sequence<Idx...>)
406 {
407 using init_list_type = std::initializer_list<std::string>;
408 auto&& ret = init_list_type{ (as_string(std::get<Idx>(_obj)))... };
409 return strvec_t(ret);
410 }
411
412 template <typename... T>
413 static strvec_t as_string_vec(const std::tuple<T...>& _obj)
414 {
415 constexpr size_t N = sizeof...(T);
417 }
418
419public:
420 template <typename Tp>
421 static strvec_t get_display_units(const Tp& _data)
422 {
423 return get_display_units_sfinae(_data, 0, 0);
424 }
425
426private:
427 template <typename Tp>
428 static auto get_display_units_sfinae(const Tp& _data, int, int)
429 -> decltype((void) _data.display_unit_array(), strvec_t{})
430 {
432 for(const auto& itr : _data.display_unit_array())
433 _ret.push_back(itr);
434 return _ret;
435 }
436
437 template <typename Tp>
438 static auto get_display_units_sfinae(const Tp& _data, int, long)
439 -> decltype((void) _data.get_display_unit(), strvec_t{})
440
441 {
442 return as_string_vec(Tp::get_display_unit());
443 }
444
445 template <typename Tp>
446 static auto get_display_units_sfinae(const Tp&, long, long) -> strvec_t
447 {
448 return strvec_t{ "" };
449 }
450
451public:
452 using sizevector_t = std::vector<size_t>;
453
454 template <typename Tp>
455 static sizevector_t get_widths(const Tp& _data)
456 {
457 return get_widths_sfinae(_data, 0);
458 }
459
460private:
461 template <typename Tp>
462 static auto get_widths_sfinae(const Tp& _data, int)
463 -> decltype((void) _data.width_array(), sizevector_t())
464 {
465 return _data.width_array();
466 }
467
468 template <typename Tp>
469 static auto get_widths_sfinae(const Tp&, long) -> sizevector_t
470 {
471 return sizevector_t{ Tp::get_width() };
472 }
473
474public:
475 //----------------------------------------------------------------------------------//
476 /// generate an attribute
477 ///
478 static string_t attribute_string(const string_t& key, const string_t& item)
479 {
480 return mpl::apply<string_t>::join("", key, "=", "\"", item, "\"");
481 }
482
483 //----------------------------------------------------------------------------------//
484 /// replace matching values in item with str
485 ///
486 static string_t replace(string_t& item, const string_t& str, const strset_t& values)
487 {
488 for(const auto& itr : values)
489 {
490 while(item.find(itr) != string_t::npos)
491 item = item.replace(item.find(itr), itr.length(), str);
492 }
493 return item;
494 }
495
496 //----------------------------------------------------------------------------------//
497 /// convert to lowercase
498 ///
500 {
501 for(auto& itr : _str)
502 itr = tolower(itr);
503 return _str;
504 }
505
506 //----------------------------------------------------------------------------------//
507 /// convert to uppercase
508 ///
510 {
511 for(auto& itr : _str)
512 itr = toupper(itr);
513 return _str;
514 }
515
516 //----------------------------------------------------------------------------------//
517 /// check if str contains any of the string items
518 ///
519 static bool contains(const string_t& str, const strset_t& items)
520 {
521 auto lstr = lowercase(str);
522 return std::any_of(items.begin(), items.end(), [&lstr](const auto& itr) {
523 return lstr.find(itr) != string_t::npos;
524 });
525 }
526
527 //----------------------------------------------------------------------------------//
528 /// shorthand for apply<string_t>::join(...)
529 ///
530 template <typename Tp, typename... Args>
531 static string_t join(Tp&& _delim, Args&&... _args)
532 {
533 return mpl::apply<string_t>::join(std::forward<Tp>(_delim),
534 std::forward<Args>(_args)...);
535 }
536
537 //----------------------------------------------------------------------------------//
538
539 static bool is_empty(const std::string& obj) { return obj.empty(); }
540
541 //----------------------------------------------------------------------------------//
542
543 template <typename Tp, typename... _Extra>
544 static bool is_empty(const std::vector<Tp, _Extra...>& obj)
545 {
546 for(const auto& itr : obj)
547 {
548 if(!itr.empty())
549 return false;
550 }
551 return true;
552 }
553
554 //----------------------------------------------------------------------------------//
555
556 template <template <typename...> class Tuple, typename... Tp>
557 static bool is_empty(const Tuple<Tp...>& obj)
558 {
559 using input_type = Tuple<Tp...>;
560 constexpr size_t N = sizeof...(Tp);
561 std::bitset<N> _bits;
565 return _bits.all();
566 }
567
568 //----------------------------------------------------------------------------------//
569
570 template <bool EnabledV, typename Arg, enable_if_t<EnabledV, int> = 0>
571 static void print_tag(std::ostream& os, const Arg& _arg)
572 {
573 if(!is_empty(_arg))
574 os << " " << _arg;
575 }
576
577 //----------------------------------------------------------------------------------//
578
579 template <bool EnabledV, typename Arg, enable_if_t<!EnabledV, int> = 0>
580 static void print_tag(std::ostream&, const Arg&)
581 {}
582};
583//
584//--------------------------------------------------------------------------------------//
585//
586template <typename Tp>
588{
589 using type = Tp;
593 using get_type = std::tuple<pointer_t, bool, bool, bool>;
594
595 template <typename Up = Tp>
597
598 template <typename Up = Tp>
600 {}
601
602 template <typename U = Tp, typename V = typename U::value_type>
604
605 template <typename U = Tp, typename V = typename U::value_type>
607 !std::is_same<typename U::storage_type,
609 int> = 0);
610
611 template <typename U = Tp, typename V = typename U::value_type>
613 std::is_same<typename U::storage_type,
615 int> = 0);
616
617 static void init();
618};
619//
620//--------------------------------------------------------------------------------------//
621//
622template <typename Tp>
624{
625 fini_storage();
626
627private:
628 // first check if type is available
629 template <typename Up = Tp>
630 TIMEMORY_INLINE void sfinae(
631 int, enable_if_t<trait::is_available<Up>::value, int> = 0) const;
632 //
633 template <typename Up = Tp>
634 TIMEMORY_INLINE void sfinae(
635 long, enable_if_t<!trait::is_available<Up>::value, int> = 0) const;
636 //
637 // second check for whether storage has finalize function
638 template <typename StorageT>
639 TIMEMORY_INLINE auto sfinae(StorageT* ptr, int) const
640 -> decltype(ptr->finalize(), void())
641 {
642 ptr->finalize();
643 }
644 //
645 template <typename StorageT>
646 TIMEMORY_INLINE void sfinae(StorageT*, long) const
647 {}
648};
649//
650//--------------------------------------------------------------------------------------//
651//
652} // namespace operation
653} // namespace tim
std::tuple_element< N, std::tuple< Types... > >::type & get(tim::auto_bundle< Tag, Types... > &obj)
const hash_alias_ptr_t hash_value_t std::string *& _ret
Definition: definition.hpp:300
std::array< bool, scope_count > input_type
Definition: types.hpp:400
typename is_available< T >::type is_available_t
Definition: types.hpp:362
Definition: kokkosp.cpp:39
std::make_integer_sequence< size_t, Num > make_index_sequence
Alias template make_index_sequence.
Definition: types.hpp:182
std::array< char *, 4 > _args
std::string string_t
Definition: utility.hpp:98
impl::index_of< Tp, Type > index_of
Definition: types.hpp:575
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
const std::string std::ostream * os
std::integer_sequence< size_t, Idx... > index_sequence
Alias template index_sequence.
Definition: types.hpp:178
Include the macros for operations.
Declare the operations types.
A very lightweight storage class which provides nothing.
Definition: declaration.hpp:51
static string_t join(SepT &&separator, Tuple &&__tup, index_sequence< Idx... >) noexcept
Definition: apply.hpp:408
common string manipulation utilities
static Tp get_entry(const Tp &_data, size_t)
static constexpr bool not_string(enable_if_t< sizeof...(Tail) !=0, int >=0)
static string_t uppercase(string_t _str)
convert to uppercase
static constexpr bool is_string(enable_if_t< sizeof...(Tail)==0, int >=0)
static strvec_t get_labels(const Tp &_data)
static strvec_t as_string_vec(const std::tuple< T... > &_obj, index_sequence< Idx... >)
static void print_tag(std::ostream &os, const Arg &_arg)
static strvec_t as_string_vec(const std::tuple< T... > &_obj)
std::vector< string_t > strvec_t
static strvec_t get_display_units(const Tp &_data)
static void write(std::vector< std::stringstream * > &_os, std::ios_base::fmtflags _format, const std::tuple< Tp... > &_data, const Wp &_width, const Pp &_prec, index_sequence< Idx... >)
std::set< string_t > strset_t
static int64_t get_labels_size(const Tp &_data)
static string_t attribute_string(const string_t &key, const string_t &item)
generate an attribute
static void print_tag(std::ostream &, const Arg &)
static sizevector_t get_widths(const Tp &_data)
static bool is_empty(const std::vector< Tp, _Extra... > &obj)
static void write(std::vector< std::stringstream * > &_os, std::ios_base::fmtflags _format, const Tp &_data, const Wp &_width, const Pp &_prec)
static std::string as_string(const Tp &_obj)
std::stringstream stringstream_t
static void write(std::vector< std::stringstream * > &_os, std::ios_base::fmtflags _format, const std::tuple< Tp... > &_data, const Wp &_width, const Pp &_prec)
std::vector< size_t > sizevector_t
static bool is_empty(const Tuple< Tp... > &obj)
static string_t join(Tp &&_delim, Args &&... _args)
shorthand for apply<string_t>::join(...)
static bool is_empty(const std::string &obj)
static auto get_entry(const Tp &_data, size_t _idx) -> decltype(get_entry_sfinae_(_data, _idx))
static string_t lowercase(string_t _str)
convert to lowercase
std::map< string_t, string_t > attributes_t
static constexpr bool is_string(enable_if_t< sizeof...(Tail) !=0, int >=0)
static size_t get_distance(const Tp &_data)
static constexpr bool not_string(enable_if_t< sizeof...(Tail)==0, int >=0)
static strvec_t as_string_vec(const T &_data)
static bool contains(const string_t &str, const strset_t &items)
check if str contains any of the string items
static string_t replace(string_t &item, const string_t &str, const strset_t &values)
replace matching values in item with str
static get_type get(enable_if_t< trait::uses_value_storage< U, V >::value, int >=0)
std::tuple< pointer_t, bool, bool, bool > get_type
init_storage(enable_if_t<!trait::uses_value_storage< Up >::value, int >=0)
static get_type get(enable_if_t<!trait::uses_value_storage< U, V >::value &&std::is_same< typename U::storage_type, component::empty_storage >::value, int >=0)
init_storage(enable_if_t< trait::uses_value_storage< Up >::value, int >=0)
static get_type get(enable_if_t<!trait::uses_value_storage< U, V >::value &&!std::is_same< typename U::storage_type, component::empty_storage >::value, int >=0)
This provides an object that can initialize the storage opaquely, e.g.
Definition: declaration.hpp:98
static storage_initializer get()
trait that signifies that an implementation for the component is available. When this is set to false...
Definition: types.hpp:355
This trait is used to determine whether the (expensive) instantiation of the storage class happens.
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56
#define TIMEMORY_RETURN_FOLD_EXPRESSION(...)
Definition: types.hpp:71