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.cpp
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#ifndef TIMEMORY_COMPONENTS_USER_BUNDLE_COMPONENTS_CPP_
26#define TIMEMORY_COMPONENTS_USER_BUNDLE_COMPONENTS_CPP_ 1
27
29
30#if !defined(TIMEMORY_USER_BUNDLE_HEADER_MODE)
31# define TIMEMORY_USER_BUNDLE_INLINE
34#else
35# define TIMEMORY_USER_BUNDLE_INLINE inline
36#endif
37
38namespace tim
39{
40namespace env
41{
42//
44{
45 static user_bundle_variables_t _instance = {
46 { component::global_bundle_idx,
47 { []() { return settings::global_components(); } } },
48 { component::ompt_bundle_idx,
49 { []() { return settings::ompt_components(); },
50 []() { return settings::trace_components(); },
51 []() { return settings::profiler_components(); },
52 []() { return settings::components(); },
53 []() { return settings::global_components(); } } },
54 { component::mpip_bundle_idx,
55 { []() { return settings::mpip_components(); },
56 []() { return settings::trace_components(); },
57 []() { return settings::profiler_components(); },
58 []() { return settings::components(); },
59 []() { return settings::global_components(); } } },
60 { component::ncclp_bundle_idx,
61 { []() { return settings::ncclp_components(); },
62 []() { return settings::mpip_components(); },
63 []() { return settings::trace_components(); },
64 []() { return settings::profiler_components(); },
65 []() { return settings::components(); },
66 []() { return settings::global_components(); } } },
67 { component::trace_bundle_idx,
68 { []() { return settings::trace_components(); },
69 []() { return settings::components(); },
70 []() { return settings::global_components(); } } },
71 { component::profiler_bundle_idx,
72 { []() { return settings::profiler_components(); },
73 []() { return settings::components(); },
74 []() { return settings::global_components(); } } },
75 };
76 return _instance;
77}
78//
79//--------------------------------------------------------------------------------------//
80//
82{
83 static user_bundle_variables_t _instance = {
84 { component::kokkosp_bundle_idx,
85 { []() { return settings::kokkos_components(); },
86 []() { return get_env<std::string>("TIMEMORY_KOKKOSP_COMPONENTS", ""); },
87 []() { return get_env<std::string>("KOKKOS_TIMEMORY_COMPONENTS", ""); },
88 []() { return settings::trace_components(); },
89 []() { return settings::profiler_components(); },
90 []() { return settings::components(); },
91 []() { return settings::global_components(); } } }
92 };
93 return _instance;
94}
95//
96//--------------------------------------------------------------------------------------//
97//
98std::vector<TIMEMORY_COMPONENT>
99get_bundle_components(const std::vector<user_bundle_spec_t>& _priority)
100{
101 std::string _custom{};
102 bool _fallthrough = false;
103 auto _replace = [&_fallthrough](const std::string& _key) {
104 const std::string _ft = "fallthrough";
105 auto _pos = _key.find(_ft);
106 if(_pos != std::string::npos)
107 {
108 _fallthrough = true;
109 return _key.substr(0, _pos) + _key.substr(_pos + _ft.length() + 1);
110 }
111 return _key;
112 };
113
114 for(const auto& itr : _priority)
115 {
116 auto _spec = itr();
117 if(_spec.length() > 0)
118 {
119 if(_spec != "none" && _spec != "NONE")
120 _custom += _replace(_spec);
121 else
122 _fallthrough = false;
123 if(!_fallthrough)
124 break;
125 }
126 }
127
128 auto _debug = (settings::instance()) ? (settings::instance()->get_debug()) : false;
129 CONDITIONAL_PRINT_HERE(_debug, "getting user bundle components: %s", _custom.c_str());
130
132}
133//
134} // namespace env
135//
136namespace component
137{
138namespace internal
139{
142{
143 return "user_bundle";
144}
147{
148 return "Generic bundle of components designed for runtime configuration by a "
149 "user via environment variables and/or direct insertion";
150}
151
153user_bundle::user_bundle(scope::config _cfg, typeid_vec_t _typeids,
154 opaque_array_t _opaque_arr, const char* _prefix)
155: m_scope{ _cfg }
156, m_prefix{ _prefix }
157, m_typeids{ std::move(_typeids) }
158, m_bundle{ std::move(_opaque_arr) }
159{}
160
162user_bundle::user_bundle(const user_bundle& rhs)
163: m_scope{ rhs.m_scope }
164, m_prefix{ rhs.m_prefix }
165, m_typeids{ rhs.m_typeids }
166, m_bundle{ rhs.m_bundle }
167{
168 for(auto& itr : m_bundle)
169 itr.set_copy(true);
170}
171
172TIMEMORY_USER_BUNDLE_INLINE user_bundle::~user_bundle()
173{
174 for(auto& itr : m_bundle)
175 itr.cleanup();
176}
177
179user_bundle::operator=(const user_bundle& rhs)
180{
181 if(this == &rhs)
182 return *this;
183
184 m_scope = rhs.m_scope;
185 m_prefix = rhs.m_prefix;
186 m_typeids = rhs.m_typeids;
187 m_bundle = rhs.m_bundle;
188 for(auto& itr : m_bundle)
189 itr.set_copy(true);
190
191 return *this;
192}
193
195user_bundle::user_bundle(user_bundle&& rhs) noexcept
196: m_scope{ std::move(rhs.m_scope) }
197, m_prefix{ std::move(rhs.m_prefix) }
198, m_typeids{ std::move(rhs.m_typeids) }
199, m_bundle{ std::move(rhs.m_bundle) }
200{
201 rhs.m_bundle.clear();
202}
203
205user_bundle::operator=(user_bundle&& rhs) noexcept
206{
207 if(this != &rhs)
208 {
209 m_scope = std::move(rhs.m_scope);
210 m_prefix = std::move(rhs.m_prefix);
211 m_typeids = std::move(rhs.m_typeids);
212 m_bundle = std::move(rhs.m_bundle);
213 rhs.m_bundle.clear();
214 }
215 return *this;
216}
217
219user_bundle::configure(opaque_array_t& _data, typeid_vec_t& _typeids, mutex_t& _mtx,
220 opaque&& obj, std::set<size_t>&& _inp)
221{
222 if(obj)
223 {
224 lock_t lk{ _mtx };
225 size_t sum = 0;
226 for(auto&& itr : _inp)
227 {
228 if(itr > 0 && contains(itr, _typeids))
229 {
231 PRINT_HERE("Skipping duplicate typeid: %lu", (unsigned long) itr);
232 return;
233 }
234 sum += itr;
235 if(itr > 0)
236 _typeids.emplace_back(itr);
237 }
238 if(sum == 0)
239 {
240 PRINT_HERE("No typeids. Sum: %lu", (unsigned long) sum);
241 return;
242 }
243 _data.emplace_back(std::move(obj));
244 }
245}
246
248user_bundle::reset(opaque_array_t& _data, typeid_vec_t& _typeids, mutex_t& _mtx)
249{
250 lock_t lk{ _mtx };
251 _data.clear();
252 _typeids.clear();
253}
254
256user_bundle::setup()
257{
258 if(!m_setup)
259 {
260 m_setup = true;
261 for(auto& itr : m_bundle)
262 itr.setup(m_prefix, m_scope);
263 }
264}
265
268{
269 setup();
270 for(auto& itr : m_bundle)
271 itr.push(m_prefix, m_scope);
272}
273
275user_bundle::sample()
276{
277 setup();
278 for(auto& itr : m_bundle)
279 itr.sample();
280}
281
284{
285 setup();
286 for(auto& itr : m_bundle)
287 itr.start();
288}
289
292{
293 for(auto& itr : m_bundle)
294 itr.stop();
295}
296
299{
300 for(auto& itr : m_bundle)
301 itr.pop();
302}
303
305user_bundle::get(void*& ptr, size_t _hash) const
306{
307 if(ptr == nullptr)
308 {
309 for(const auto& itr : m_bundle)
310 {
311 itr.get(ptr, _hash);
312 if(ptr)
313 break;
314 }
315 }
316}
317
320{
321 m_prefix = _prefix;
322 m_setup = false;
323}
324
326user_bundle::set_scope(const scope::config& val)
327{
328 m_scope = val;
329 m_setup = false;
330}
331
333user_bundle::insert(opaque&& obj, typeid_set_t&& _typeids)
334{
335 if(obj)
336 {
337 size_t sum = 0;
338 for(auto&& itr : _typeids)
339 {
340 if(itr > 0 && contains(itr, m_typeids))
341 {
343 PRINT_HERE("Skipping duplicate typeid: %lu", (unsigned long) itr);
344 return;
345 }
346 sum += itr;
347 if(itr > 0)
348 m_typeids.emplace_back(itr);
349 }
350 if(sum == 0)
351 {
352 PRINT_HERE("No typeids. Sum: %lu", (unsigned long) sum);
353 return;
354 }
355 m_bundle.emplace_back(std::move(obj));
356 }
357}
358
360user_bundle::update_statistics(bool _v) const
361{
362 for(const auto& itr : m_bundle)
363 itr.update_statistics(_v);
364}
365
367user_bundle::contains(size_t _val, const typeid_vec_t& _targ)
368{
369 return std::any_of(_targ.begin(), _targ.end(),
370 [&_val](auto itr) { return (itr == _val); });
371}
372
373} // namespace internal
374} // namespace component
375} // namespace tim
376
377#endif // TIMEMORY_COMPONENTS_USER_BUNDLE_COMPONENTS_CPP_
Implementation of the user_bundle component(s)
Forward declaration of user_bundle components. User-bundles are similar to the classical profiling in...
#define TIMEMORY_USER_BUNDLE_INLINE
Definition: components.cpp:31
STL namespace.
std::vector< TIMEMORY_COMPONENT > get_bundle_components(const std::vector< user_bundle_spec_t > &_priority)
Definition: components.cpp:99
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 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
mpip_components
Definition: settings.cpp:1690
char const std::string & _prefix
Definition: config.cpp:55
profiler_components
Definition: settings.cpp:1696
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
std::vector< TIMEMORY_COMPONENT > enumerate_components(const Container< StringT, ExtraArgs... > &component_names)
description: use this function to generate an array of enumerations from a list of string that can be...
Definition: enumerate.hpp:62
ompt_components
Definition: settings.cpp:1688
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
ncclp_components
Definition: settings.cpp:1692
auto get(const auto_bundle< Tag, Types... > &_obj)
trace_components
Definition: settings.cpp:1694
global_components
Definition: settings.cpp:1682
components
Definition: settings.cpp:1700
kokkos_components
Definition: settings.cpp:1698
ContainerT delimit(const std::string &line, const std::string &delimiters="\"',;: ", PredicateT &&predicate=[](const std::string &s) -> std::string { return s;})
Definition: delimit.hpp:68
static settings * instance()
Definition: settings.hpp:536
#define CONDITIONAL_PRINT_HERE(CONDITION,...)
Definition: macros.hpp:183
#define PRINT_HERE(...)
Definition: macros.hpp:152