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.
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/user_bundle/components.hpp
27 * \brief Implementation of the user_bundle component(s)
28 */
29
30#pragma once
31
32#include "timemory/api.hpp"
34#include "timemory/components/user_bundle/backends.hpp"
36#include "timemory/enum.h"
42#include "timemory/units.hpp"
44
45#include <algorithm>
46#include <functional>
47#include <regex>
48#include <string>
49#include <unordered_map>
50#include <utility>
51#include <vector>
52
53//======================================================================================//
54//
55namespace tim
56{
57//
58//--------------------------------------------------------------------------------------//
59//
60namespace env
61{
62//
63using user_bundle_spec_t = std::function<std::string()>;
64//
66 std::unordered_map<size_t, std::vector<user_bundle_spec_t>>;
67//
68//--------------------------------------------------------------------------------------//
69/// non-static so that projects can globally change this for their project/API
70template <typename ApiT>
72{
73 static user_bundle_variables_t _instance{};
74 return _instance;
75}
76//
77#if defined(TIMEMORY_USER_BUNDLE_HEADER_MODE)
78/// static so that projects cannot globally change this
80static inline user_bundle_variables_t& get_user_bundle_variables(project::kokkosp);
81//
82inline std::vector<TIMEMORY_COMPONENT>
83get_bundle_components(const std::vector<user_bundle_spec_t>& _priority);
84#else
85/// static so that projects cannot globally change this
88//
89std::vector<TIMEMORY_COMPONENT>
90get_bundle_components(const std::vector<user_bundle_spec_t>& _priority);
91#endif
92//
93//--------------------------------------------------------------------------------------//
94//
95template <size_t Idx, typename Api, typename AltApi = Api>
96void
97initialize_bundle(AltApi _api = AltApi{})
98{
99 using user_bundle_type = component::user_bundle<Idx, Api>;
100 auto& variables = env::get_user_bundle_variables(_api);
101 auto itr = variables.find(Idx);
102 if(itr != variables.end())
103 {
105 (settings::instance()) ? (settings::instance()->get_debug()) : false,
106 "getting user bundle components for type %s (%s)",
107 demangle<user_bundle_type>().c_str(), user_bundle_type::label().c_str());
108
109 auto _enum = env::get_bundle_components(itr->second);
110 tim::configure<user_bundle_type>(_enum);
111 }
112}
113//
114} // namespace env
115//
116//--------------------------------------------------------------------------------------//
117//
118namespace component
119{
120//
121//--------------------------------------------------------------------------------------//
122//
123// USER BUNDLE
124//
125//--------------------------------------------------------------------------------------//
126//
127namespace internal
128{
129struct user_bundle
130{
131public:
132 using mutex_t = std::mutex;
133 using lock_t = std::unique_lock<mutex_t>;
134 using opaque_array_t = std::vector<opaque>;
135 using typeid_vec_t = std::vector<size_t>;
136 using typeid_set_t = std::set<size_t>;
137
138 static std::string label();
139 static std::string description();
140 static void record() {}
141
142public:
143 user_bundle(scope::config _cfg, typeid_vec_t _typeids, opaque_array_t _opaque_arr,
144 const char* _prefix = nullptr);
145 ~user_bundle();
146 user_bundle(const user_bundle& rhs);
147 user_bundle(user_bundle&& rhs) noexcept;
148 user_bundle& operator=(const user_bundle& rhs);
149 user_bundle& operator=(user_bundle&& rhs) noexcept;
150
151public:
152 /// Configure the tool for a specific component
153 static void configure(opaque_array_t& _data, typeid_vec_t& _typeids, mutex_t& _mtx,
154 opaque&& obj, std::set<size_t>&& _inp);
155
156 /// Explicitly clear the previous configurations
157 static void reset(opaque_array_t& _data, typeid_vec_t& _typeids, mutex_t& _mtx);
158
159public:
160 void setup();
161 void push();
162 void sample();
163 void start();
164 void stop();
165 void pop();
166 void get(void*& ptr, size_t _hash) const;
167 void set_prefix(const char* _prefix);
168 void set_scope(const scope::config& val);
169 void update_statistics(bool _v) const;
170 size_t size() const { return m_bundle.size(); }
171 const char* get_prefix() const { return m_prefix; }
172 scope::config get_scope() const { return m_scope; }
173
174public:
175 // Configure the tool for a specific component
176 void insert(opaque&& obj, typeid_set_t&& _typeids);
177
178protected:
179 bool m_setup = false;
180 scope::config m_scope = {};
181 const char* m_prefix = nullptr;
182 typeid_vec_t m_typeids = {};
183 opaque_array_t m_bundle = {};
184
185protected:
186 static bool contains(size_t _val, const typeid_vec_t& _targ);
187};
188} // namespace internal
189//
190template <size_t Idx, typename Tag>
192: public base<user_bundle<Idx, Tag>, void>
194, private internal::user_bundle
195{
196public:
197 static constexpr auto index = Idx;
198 using tag_type = Tag;
199 using mutex_t = std::mutex;
200 using start_func_t = std::function<void*(const std::string&, scope::config)>;
201 using stop_func_t = std::function<void(void*)>;
202 using get_func_t = std::function<void(void*, void*&, size_t)>;
203 using delete_func_t = std::function<void(void*)>;
204 using opaque_array_t = std::vector<opaque>;
205 using typeid_vec_t = std::vector<size_t>;
206 using typeid_set_t = std::set<size_t>;
207
208 using value_type = void;
212
213 friend struct operation::record<this_type>;
214 friend struct operation::start<this_type>;
215 friend struct operation::stop<this_type>;
216 friend struct operation::set_started<this_type>;
217 friend struct operation::set_stopped<this_type>;
218
219 static size_t bundle_size() { return get_data().size(); }
220 static void global_init(bool _preinit = false) TIMEMORY_VISIBILITY("default");
221 static void global_init(storage_type*) { global_init(false); }
222
224 using internal::user_bundle::label;
226
227private:
228 using internal::user_bundle::m_bundle;
229 using internal::user_bundle::m_prefix;
230 using internal::user_bundle::m_scope;
231 using internal::user_bundle::m_setup;
232 using internal::user_bundle::m_typeids;
233
234public:
235 //----------------------------------------------------------------------------------//
236 // Captures the statically-defined data so these can be changed without
237 // affecting this instance
238 //
240 : internal::user_bundle{ scope::get_default(), get_typeids(),
241 (persistent_init(), get_data()) }
242 {}
243
244 explicit user_bundle(const char* _prefix, scope::config _scope = scope::get_default())
245 : internal::user_bundle{ _scope, get_typeids(), (persistent_init(), get_data()),
246 _prefix }
247 {}
248
249 user_bundle(const char* _prefix, opaque_array_t _bundle_vec, typeid_vec_t _typeids,
250 scope::config _scope = scope::get_default())
251 : internal::user_bundle{ _scope, std::move(_typeids), std::move(_bundle_vec),
252 _prefix }
253 {}
254
255 user_bundle(const char* _prefix, opaque_array_t _bundle_vec, typeid_set_t _typeids,
256 scope::config _scope = scope::get_default())
257 : internal::user_bundle{ _scope, typeid_vec_t{}, std::move(_bundle_vec), _prefix }
258 {
259 m_typeids.reserve(_typeids.size());
260 for(const auto& itr : _typeids)
261 m_typeids.emplace_back(itr);
262 }
263
264 ~user_bundle() = default;
265 user_bundle(const user_bundle&) = default;
266 user_bundle(user_bundle&& rhs) noexcept = default;
267
268 user_bundle& operator=(const user_bundle& rhs) = default;
269 user_bundle& operator=(user_bundle&& rhs) noexcept = default;
270
271public:
272 // Configure the tool for a specific component
273 static void configure(opaque&& obj, std::set<size_t>&& _typeids)
274 {
275 internal::user_bundle::configure(get_data(), get_typeids(), get_lock(),
276 std::forward<opaque>(obj),
277 std::forward<std::set<size_t>>(_typeids));
278 }
279
280 template <typename Type, typename... Types, typename... Args>
281 static void configure(Args&&... args)
282 {
283 this_type::configure(factory::get_opaque<Type>(std::forward<Args>(args)...),
284 factory::get_typeids<Type>());
285
287 this_type::configure(factory::get_opaque<Types>(std::forward<Args>(args)...),
288 factory::get_typeids<Types>()));
289 }
290
291 // Explicitly clear the previous configurations
292 static void reset()
293 {
295 "Resetting %s", demangle<this_type>().c_str());
297 }
298
299public:
300 using internal::user_bundle::get_prefix;
301 using internal::user_bundle::get_scope;
305 using internal::user_bundle::sample;
308 using internal::user_bundle::setup;
309 using internal::user_bundle::size;
312 using internal::user_bundle::update_statistics;
313
314 using base_type::operator+=;
315 using base_type::operator-=;
335
336 void clear()
337 {
339 stop();
340 m_typeids.clear();
341 m_bundle.clear();
342 m_setup = false;
343 }
344
345 template <typename T>
346 T* get()
347 {
348 auto _typeid_hash = typeid_hash<T>();
349 void* void_ptr = nullptr;
350 for(auto& itr : m_bundle)
351 {
352 itr.get(void_ptr, _typeid_hash);
353 if(void_ptr)
354 return static_cast<T*>(void_ptr);
355 }
356 return static_cast<T*>(void_ptr);
357 }
358
359 void get() const {}
360
361 void get(void*& ptr, size_t _typeid_hash) const
362 {
363 base_type::get(ptr, _typeid_hash);
364 internal::user_bundle::get(ptr, _typeid_hash);
365 }
366
367public:
368 template <typename Type, typename... Types, typename... Args>
369 void insert(Args... args)
370 {
371 this->insert(factory::get_opaque<Type>(args...), factory::get_typeids<Type>());
372 TIMEMORY_FOLD_EXPRESSION(this->insert(factory::get_opaque<Types>(args...),
373 factory::get_typeids<Types>()));
374 }
375
376private:
377 static bool persistent_init();
378 struct persistent_data;
379 static persistent_data& get_persistent_data() TIMEMORY_VISIBILITY("default");
380
381 struct persistent_data
382 {
383 volatile bool m_init = false;
384 bool m_preinit = false;
385 mutex_t m_lock;
386 opaque_array_t m_data = {};
387 typeid_vec_t m_typeids = {};
388 std::shared_ptr<settings> m_settings = settings::shared_instance();
389
390 bool init(bool _preinit = false)
391 {
392 if(!m_init)
393 {
394 if(_preinit)
395 m_preinit = true;
396 if(m_settings && m_settings->get_initialized())
397 {
398 if(m_preinit)
399 reset();
400 m_init = true; // comma operator
401 }
402 if(m_init || _preinit)
403 env::initialize_bundle<Idx, Tag>();
404 }
405 return m_init;
406 }
407 };
408
409public:
410 /// template instantiation-specific static opaque array
411 static opaque_array_t& get_data() { return get_persistent_data().m_data; }
412
413 /// template instantiation-specific static set of type identifiers
414 static typeid_vec_t& get_typeids() { return get_persistent_data().m_typeids; }
415
416 /// template instantiation-specific static mutex
417 static mutex_t& get_lock() { return get_persistent_data().m_lock; }
418};
419//
420//--------------------------------------------------------------------------------------//
421//
422template <size_t Idx, typename Tag>
423void
425{
427 PRINT_HERE("Global initialization of %s", demangle<this_type>().c_str());
428 get_persistent_data().init(_preinit);
429}
430//
431//--------------------------------------------------------------------------------------//
432//
433template <size_t Idx, typename Tag>
436{
437 static persistent_data _instance{};
438 return _instance;
439}
440//
441//--------------------------------------------------------------------------------------//
442//
443template <size_t Idx, typename Tag>
444bool
445user_bundle<Idx, Tag>::persistent_init()
446{
447 return get_persistent_data().init();
448}
449//
450//--------------------------------------------------------------------------------------//
451//
452} // namespace component
453} // namespace tim
454//
455//======================================================================================//
456
457#if defined(TIMEMORY_USER_BUNDLE_HEADER_MODE)
459#endif
Forward declaration of user_bundle components. User-bundles are similar to the classical profiling in...
STL namespace.
std::vector< TIMEMORY_COMPONENT > get_bundle_components(const std::vector< user_bundle_spec_t > &_priority)
Definition: components.cpp:99
void initialize_bundle(AltApi _api=AltApi{})
Definition: components.hpp:97
std::function< std::string()> user_bundle_spec_t
Definition: components.hpp:63
std::unordered_map< size_t, std::vector< user_bundle_spec_t > > user_bundle_variables_t
Definition: components.hpp:66
user_bundle_variables_t & get_user_bundle_variables(TIMEMORY_API)
static so that projects cannot globally change this
Definition: components.cpp:43
_reported insert(_hash_id)
void set_scope(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:810
void set_prefix(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:774
void record(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:634
void pop(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:739
void stop(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:386
void push(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:704
void reset(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:599
void start(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:316
Definition: kokkosp.cpp:39
char const std::string & _prefix
Definition: config.cpp:55
void configure(std::initializer_list< EnumT > components, Args &&... args)
Definition: configure.hpp:50
std::recursive_mutex mutex_t
Recursive mutex is used for convenience since the performance penalty vs. a regular mutex is not real...
Definition: locking.hpp:38
void init(Args &&... args)
Definition: types.hpp:111
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
auto get(const auto_bundle< Tag, Types... > &_obj)
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: config.cpp:312
void set_is_transient(bool v)
Definition: data.hpp:464
bool get_is_flat() const
Definition: data.hpp:458
void set_is_on_stack(bool v)
Definition: data.hpp:463
auto get_iterator() const
bool get_depth_change() const
Definition: data.hpp:459
void set_is_running(bool v)
Definition: data.hpp:462
void set_iterator(graph_iterator itr)
int64_t get_laps() const
add a sample
bool get_is_on_stack() const
Definition: data.hpp:456
void set_stopped()
store that stop has been called
bool get_is_transient() const
Definition: data.hpp:457
void set_depth_change(bool v)
Definition: data.hpp:466
bool get_is_running() const
Definition: data.hpp:455
static opaque get_opaque(scope::config)
get the opaque binding for user-bundle
storage< Tp, Value > storage_type
auto get() const
retrieve the current measurement value in the units for the type
bool get_is_invalid() const
Definition: data.hpp:460
void set_is_invalid(bool v)
Definition: data.hpp:467
void set_is_flat(bool v)
Definition: data.hpp:465
void set_started()
store that start has been called
void set_laps(int64_t v)
A very lightweight storage class which provides nothing.
Definition: declaration.hpp:51
user_bundle & operator=(const user_bundle &rhs)=default
user_bundle(const char *_prefix, opaque_array_t _bundle_vec, typeid_set_t _typeids, scope::config _scope=scope::get_default())
Definition: components.hpp:255
void get(void *&ptr, size_t _typeid_hash) const
Definition: components.hpp:361
static typeid_vec_t & get_typeids()
template instantiation-specific static set of type identifiers
Definition: components.hpp:414
user_bundle(const user_bundle &)=default
static void configure(opaque &&obj, std::set< size_t > &&_typeids)
Definition: components.hpp:273
static void global_init(storage_type *)
Definition: components.hpp:221
std::function< void(void *, void *&, size_t)> get_func_t
Definition: components.hpp:202
static void global_init(bool _preinit=false)
Definition: components.hpp:424
static constexpr auto index
Definition: components.hpp:197
user_bundle & operator=(user_bundle &&rhs) noexcept=default
user_bundle(user_bundle &&rhs) noexcept=default
static size_t bundle_size()
Definition: components.hpp:219
void insert(Args... args)
Definition: components.hpp:369
static opaque_array_t & get_data()
template instantiation-specific static opaque array
Definition: components.hpp:411
user_bundle(const char *_prefix, opaque_array_t _bundle_vec, typeid_vec_t _typeids, scope::config _scope=scope::get_default())
Definition: components.hpp:249
static void configure(Args &&... args)
Definition: components.hpp:281
user_bundle(const char *_prefix, scope::config _scope=scope::get_default())
Definition: components.hpp:244
std::function< void(void *)> delete_func_t
Definition: components.hpp:203
std::vector< opaque > opaque_array_t
Definition: components.hpp:204
static mutex_t & get_lock()
template instantiation-specific static mutex
Definition: components.hpp:417
std::function< void(void *)> stop_func_t
Definition: components.hpp:201
std::vector< size_t > typeid_vec_t
Definition: components.hpp:205
std::function< void *(const std::string &, scope::config)> start_func_t
Definition: components.hpp:200
This operation attempts to call a member function which the component provides to internally store wh...
Definition: types.hpp:469
This operation attempts to call a member function which the component provides to internally store wh...
Definition: types.hpp:502
this data type encodes the options of storage scope. The default is hierarchical (tree) scope....
Definition: types.hpp:453
static pointer_t shared_instance()
static settings * instance()
Definition: settings.hpp:536
#define CONDITIONAL_PRINT_HERE(CONDITION,...)
Definition: macros.hpp:183
#define PRINT_HERE(...)
Definition: macros.hpp:152
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56