Geant4-11
G4Profiler.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4Profiler
27//
28// Class description:
29//
30// Class providing the internal profiling interface for Geant4.
31
32// Author: Jonathan Madsen, LBNL - November 2020
33// --------------------------------------------------------------------
34#ifndef G4Profiler_hh
35#define G4Profiler_hh 1
36
37// Fundamental definitions
38#ifndef G4GMAKE
39# include "G4GlobalConfig.hh"
40#endif
41
42// for meta-programming stuff
43#include "G4Profiler.icc"
44
45#if defined(GEANT4_USE_TIMEMORY)
46# include <timemory/utility/argparse.hpp>
47#endif
48
49#include "globals.hh"
50
51#include <cstddef>
52#include <functional>
53#include <string>
54#include <utility>
55#include <type_traits>
56#include <tuple>
57#include <vector>
58#include <array>
59
60//----------------------------------------------------------------------------//
61
62class G4Run;
63class G4Event;
64class G4Track;
65class G4Step;
66
68{
69 enum : size_t
70 {
71 Run = 0,
77 };
78};
79
81{
82 enum : int
83 {
84 Query = 0,
86 Tool
87 };
88};
89
90//----------------------------------------------------------------------------//
91
93{
94 public:
95 using array_type = std::array<bool, G4ProfileType::TypeEnd>;
96
97#if defined(GEANT4_USE_TIMEMORY)
98 using ArgumentParser = tim::argparse::argument_parser;
99#else
101 {
102 explicit ArgumentParser(std::string) {}
103 };
104#endif
105
106 static void Configure(const std::vector<std::string>& args);
107 static void Configure(int argc, char** argv);
108 static void Configure(ArgumentParser&, const std::vector<std::string>& args);
109 static void Configure(ArgumentParser&, int argc, char** argv);
110 static void Finalize();
111
112 static bool GetEnabled(size_t v) { return GetEnabled().at(v); }
113 static void SetEnabled(size_t v, bool val) { GetEnabled().at(v) = val; }
114
115 static bool GetPerEvent() { return GetPerEventImpl(); }
116 static void SetPerEvent(bool val) { GetPerEventImpl() = val; }
117
118 private:
119 static array_type& GetEnabled();
120 static bool& GetPerEventImpl()
121 {
122 static bool _value = false;
123 return _value;
124 }
125};
126
127//----------------------------------------------------------------------------//
128// maps enumerations to types
129//
130template <size_t Category>
132{
133 using type = void;
134};
135
136template <size_t Category>
138
139template <>
141{
142 using type = const G4Run*;
143};
144
145template <>
147{
148 using type = const G4Event*;
149};
150
151template <>
153{
154 using type = const G4Track*;
155};
156
157template <>
159{
160 using type = const G4Step*;
161};
162
163template <>
165{
166 using type = const std::string&;
167};
168
169//----------------------------------------------------------------------------//
170// default set of profiler args
171template <size_t Category>
173{
174 // this resolves to the G4ProfilerObject type-trait above, e.g.
175 // "const G4Step*" when category is G4ProfileType::Step
177
178 // two-dimensional type-list where each inner type-list is a set
179 // of arguments to support creating a profiler type from
180 using type = G4TypeList<G4PROFILER_ARG_SET(value_type)>;
181 // so above means there are functors in use which apply:
182 //
183 // G4StepProfiler _profiler(const G4Step*);
184 //
185};
186
187template <size_t Category>
189
190//----------------------------------------------------------------------------//
191
192template <size_t Category, typename RetT, typename CommonT = G4CommonTypeList<>>
194{
195 using type = G4Impl::Functors_t<RetT, CommonT, G4ProfilerArgs_t<Category>>;
196};
197
198template <size_t Category, typename RetT, typename... CommonT>
200 typename G4ProfilerFunctors<Category, RetT,
201 G4CommonTypeList<CommonT...>>::type;
202
203//----------------------------------------------------------------------------//
204
205#ifdef GEANT4_USE_TIMEMORY
206
207// Pre-declare the timemory component that will be used
208namespace tim
209{
210 namespace component
211 {
212 template <size_t, typename Tag>
213 struct user_bundle;
214 } // namespace component
215
216 template <typename... Types>
217 class auto_tuple;
218
219 template <typename Tag, typename... Types>
220 class auto_bundle;
221} // namespace tim
222
223namespace g4tim
224{
225 using namespace tim;
226 using tim::component::user_bundle;
227
228 struct G4api : public tim::concepts::api
229 {};
230
231 using ProfilerArgparser = argparse::argument_parser;
232
233} // namespace g4tim
234
240
241template <typename... Types>
242using G4ProfilerBundle = g4tim::auto_bundle<g4tim::G4api, Types...>;
243
244#else
245
246namespace g4tim
247{
249 {};
250
252 template <typename... Types>
253 struct handler
254 {
255 template <typename... Args>
256 handler(Args&&...)
257 {}
258 ~handler() = default;
259 handler(const handler&) = default;
260 handler(handler&&) = default;
261 handler& operator=(const handler&) = default;
262 handler& operator=(handler&&) = default;
263
264 void record() {}
265 template <typename... Args>
266 void start(Args&&...)
267 {}
268 template <typename... Args>
269 void stop(Args&&...)
270 {}
271 void push() {}
272 void pop() {}
273 void reset() {}
274 void report_at_exit(bool) {}
275 template <typename... Args>
276 void mark_begin(Args&&...)
277 {}
278 template <typename... Args>
279 void mark_end(Args&&...)
280 {}
281 friend std::ostream& operator<<(std::ostream& os, const handler&)
282 {
283 return os;
284 }
285 };
286
287 template <size_t Idx, typename Tp>
289 {
290 template <typename... Args>
291 user_bundle(Args&&...)
292 {}
293
294 template <typename... Types, typename... Args>
295 static void configure(Args&&...)
296 {}
297
298 static void reset() {}
299 };
300
301} // namespace g4tim
302
308
309template <typename... Types>
311
312#endif
313
314//----------------------------------------------------------------------------//
315
323template <size_t Category>
325{
326 public:
329
330 static constexpr size_t arg_sets =
331 G4TypeListSize<G4ProfilerArgs_t<Category>>::value;
332
335 using ToolFunc_t = std::tuple<std::function<type*(const std::string&)>>;
336
337 public:
338 // when constructed with no args, should call operator()
339 G4ProfilerConfig() = default;
340
341 // constructor calls Query(...), Label(...), Tool(...)
342 template <typename Arg, typename... Args>
343 G4ProfilerConfig(Arg, Args...);
344
345 // will delete m_bundle is allocated
347
348 // default the move-constructor and move-assignment
351
352 // do not allow copy-construct and copy-assign bc of raw pointer
355
356 // if constructed without args, this function should be called
357 template <typename... Args>
358 bool operator()(Args...);
359
360 // provide nullptr check
361 operator bool() const { return (m_bundle != nullptr); }
362
363 private:
364 type* m_bundle = nullptr;
365
367 {
368 static QueryFunc_t _value;
369 return _value;
370 }
371
373 {
374 static LabelFunc_t _value;
375 return _value;
376 }
377
379 {
380 static ToolFunc_t _value;
381 return _value;
382 }
383
384 public:
385 // invokes the functor that determines whether to enable profiling
386 template <typename... Args>
387 static bool Query(Args... _args);
388
389 // invokes the functor for generating a Label when profiling is enabled
390 template <typename... Args>
391 static std::string Label(Args... _args);
392
393 // invokes the functor for configuring a Tool instance
394 template <typename... Args>
395 static type* Tool(const std::string&);
396
397 using QueryHandler_t = FuncHandler<this_type, QueryFunc_t, bool>;
398 using LabelHandler_t = FuncHandler<this_type, LabelFunc_t, std::string>;
399 using ToolHandler_t = FuncHandler<this_type, ToolFunc_t, type*>;
400
403
406
409
410 private:
411 template <bool B, typename Lhs, typename Rhs>
412 using conditional_t = typename std::conditional<B, Lhs, Rhs>::type;
413
414 // this provides the global statics for the functors
415 template <int Idx>
417 {
418 // determine the functor type
422
425 // default member initialization
427 };
428
429 template <int Idx>
431
432 template <int Idx>
434};
435
436//----------------------------------------------------------------------------//
437
438// alias for getting type
439template <size_t Category>
441
442// ----------------------------------------------------------------------
443
444template <size_t Cat>
445template <typename Arg, typename... Args>
447{
448 this->operator()(_arg, _args...);
449}
450
451// ----------------------------------------------------------------------
452
453template <size_t Cat>
454template <typename... Args>
456{
457 if(Query(_args...))
458 {
459 m_bundle = Tool(Label(_args...));
460 if(m_bundle)
461 m_bundle->start(_args...);
462 return (m_bundle != nullptr);
463 }
464 return false;
465}
466
467// ----------------------------------------------------------------------
468
469// invokes the functor that determines whether to enable profiling
470template <size_t Cat>
471template <typename... Args>
473{
474 return QueryHandler_t{ GetPersistent<G4ProfileOp::Query>().m_functor }(
475 _args...);
476}
477
478//----------------------------------------------------------------------------//
479
480// invokes the functor for generating a label when profiling is enabled
481template <size_t Cat>
482template <typename... Args>
483std::string G4ProfilerConfig<Cat>::Label(Args... _args)
484{
485 return LabelHandler_t{ GetPersistent<G4ProfileOp::Label>().m_functor }(
486 _args...);
487}
488
489//----------------------------------------------------------------------------//
490
491// invokes the functor for configuring a tool instance
492template <size_t Cat>
493template <typename... Args>
495 const std::string& _args)
496{
497 return ToolHandler_t{ GetPersistent<G4ProfileOp::Tool>().m_functor }(_args);
498}
499
500//----------------------------------------------------------------------------//
501
502// ensure that any implicit instantiations of the G4ProfilerConfig
503// are not done in another translation units because we will
504// explicitly instantiate G4ProfilerConfig in the .cc file
505
506// line breaks make this much harder to read
507// clang-format off
508extern template class G4ProfilerConfig<G4ProfileType::Run>;
509extern template class G4ProfilerConfig<G4ProfileType::Event>;
510extern template class G4ProfilerConfig<G4ProfileType::Track>;
511extern template class G4ProfilerConfig<G4ProfileType::Step>;
512extern template class G4ProfilerConfig<G4ProfileType::User>;
517extern template G4ProfilerConfig<G4ProfileType::User>::G4ProfilerConfig(const std::string&);
518// clang-format on
519
520//----------------------------------------------------------------------------//
521
522#ifndef GEANT4_USE_TIMEMORY
523
524# include <ostream>
525# include <string>
526
527#endif
528
529#if defined(GEANT4_USE_TIMEMORY)
530// two macros below create a unique variable name based on the line number
531# define G4USER_PROFILER_VAR_JOIN(X, Y) X##Y
532# define G4USER_PROFILER_VAR(Y) G4USER_PROFILER_VAR_JOIN(g4user_profiler_, Y)
533
534// inserts just the string
535# define G4USER_SCOPED_PROFILE(...) \
536 G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)( \
537 TIMEMORY_JOIN("", __VA_ARGS__))
538
539// inserts the function
540# define G4USER_SCOPED_PROFILE_FUNC(...) \
541 G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)( \
542 TIMEMORY_JOIN("", __FUNCTION__, "/", __VA_ARGS__))
543
544// inserts the function and file
545# define G4USER_SCOPED_PROFILE_FUNC_FILE(...) \
546 G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)( \
547 TIMEMORY_JOIN("", __FUNCTION__, '@', __FILE__, '/', __VA_ARGS__))
548
549// inserts the function, file, and line number
550# define G4USER_SCOPED_PROFILE_FUNC_FILE_LINE(...) \
551 G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)( \
552 TIMEMORY_JOIN("", __FUNCTION__, '@', __FILE__, ':', __LINE__, '/', \
553 __VA_ARGS__))
554#else
555# define G4USER_SCOPED_PROFILE(...)
556# define G4USER_SCOPED_PROFILE_FUNC(...)
557# define G4USER_SCOPED_PROFILE_FUNC_FILE(...)
558# define G4USER_SCOPED_PROFILE_FUNC_FILE_LINE(...)
559#endif
560
561#endif // G4Profiler_hh
G4double(* function)(G4double)
typename G4ProfilerConfig< Category >::type G4ProfilerConfig_t
Definition: G4Profiler.hh:440
typename G4ProfilerFunctors< Category, RetT, G4CommonTypeList< CommonT... > >::type G4ProfilerFunctors_t
Definition: G4Profiler.hh:201
typename G4ProfilerObject< Category >::type G4ProfilerObject_t
Definition: G4Profiler.hh:137
typename G4ProfilerArgs< Category >::type G4ProfilerArgs_t
Definition: G4Profiler.hh:188
static char ** args
Definition: G4Xt.cc:51
FuncHandler< this_type, LabelFunc_t, std::string > LabelHandler_t
Definition: G4Profiler.hh:398
static QueryHandler_t GetFallbackQueryFunctor()
Definition: G4Profiler.cc:444
FuncHandler< this_type, ToolFunc_t, type * > ToolHandler_t
Definition: G4Profiler.hh:399
std::tuple< std::function< type *(const std::string &)> > ToolFunc_t
Definition: G4Profiler.hh:335
static PersistentSettings< Idx > & GetPersistentFallback()
static ToolHandler_t GetToolFunctor()
Definition: G4Profiler.cc:434
bool operator()(Args...)
Definition: G4Profiler.hh:455
static ToolHandler_t GetFallbackToolFunctor()
Definition: G4Profiler.cc:466
G4ProfilerConfig(const G4ProfilerConfig &)=delete
static LabelFunc_t & GetLables()
Definition: G4Profiler.hh:372
static constexpr size_t arg_sets
Definition: G4Profiler.hh:330
G4ProfilerConfig & operator=(const G4ProfilerConfig &)=delete
static PersistentSettings< Idx > & GetPersistent()
static QueryHandler_t GetQueryFunctor()
Definition: G4Profiler.cc:416
G4ProfilerBundle< g4tim::user_bundle< Category, G4ProfileType > > type
Definition: G4Profiler.hh:327
G4ProfilerFunctors_t< Category, std::string > LabelFunc_t
Definition: G4Profiler.hh:334
static QueryFunc_t & GetQueries()
Definition: G4Profiler.hh:366
static type * Tool(const std::string &)
Definition: G4Profiler.hh:494
static bool Query(Args... _args)
Definition: G4Profiler.hh:472
static ToolFunc_t & GetTools()
Definition: G4Profiler.hh:378
typename std::conditional< B, Lhs, Rhs >::type conditional_t
Definition: G4Profiler.hh:412
static LabelHandler_t GetLabelFunctor()
Definition: G4Profiler.cc:425
G4ProfilerConfig(G4ProfilerConfig &&)=default
static LabelHandler_t GetFallbackLabelFunctor()
Definition: G4Profiler.cc:455
G4ProfilerConfig()=default
FuncHandler< this_type, QueryFunc_t, bool > QueryHandler_t
Definition: G4Profiler.hh:397
G4ProfilerFunctors_t< Category, bool > QueryFunc_t
Definition: G4Profiler.hh:333
static std::string Label(Args... _args)
Definition: G4Profiler.hh:483
G4ProfilerConfig & operator=(G4ProfilerConfig &&)=default
static void Configure(const std::vector< std::string > &args)
Definition: G4Profiler.cc:91
static void SetEnabled(size_t v, bool val)
Definition: G4Profiler.hh:113
static void SetPerEvent(bool val)
Definition: G4Profiler.hh:116
std::array< bool, G4ProfileType::TypeEnd > array_type
Definition: G4Profiler.hh:95
static bool GetPerEvent()
Definition: G4Profiler.hh:115
static bool GetEnabled(size_t v)
Definition: G4Profiler.hh:112
static void Finalize()
Definition: G4Profiler.cc:331
static array_type & GetEnabled()
Definition: G4Profiler.cc:43
static bool & GetPerEventImpl()
Definition: G4Profiler.hh:120
Definition: G4Run.hh:49
Definition: G4Step.hh:62
G4TypeList< G4PROFILER_ARG_SET(value_type)> type
Definition: G4Profiler.hh:180
G4ProfilerObject_t< Category > value_type
Definition: G4Profiler.hh:176
conditional_t< Idx==G4ProfileOp::Query, QueryFunc_t, conditional_t< Idx==G4ProfileOp::Label, LabelFunc_t, ToolFunc_t > > functor_type
Definition: G4Profiler.hh:421
G4Impl::Functors_t< RetT, CommonT, G4ProfilerArgs_t< Category > > type
Definition: G4Profiler.hh:195
this provides a dummy wrapper for the profiling
Definition: G4Profiler.hh:254
void start(Args &&...)
Definition: G4Profiler.hh:266
void mark_begin(Args &&...)
Definition: G4Profiler.hh:276
handler(Args &&...)
Definition: G4Profiler.hh:256
void stop(Args &&...)
Definition: G4Profiler.hh:269
void report_at_exit(bool)
Definition: G4Profiler.hh:274
handler(handler &&)=default
handler & operator=(const handler &)=default
friend std::ostream & operator<<(std::ostream &os, const handler &)
Definition: G4Profiler.hh:281
handler(const handler &)=default
handler & operator=(handler &&)=default
void mark_end(Args &&...)
Definition: G4Profiler.hh:279
~handler()=default
static void configure(Args &&...)
Definition: G4Profiler.hh:295
user_bundle(Args &&...)
Definition: G4Profiler.hh:291
static void reset()
Definition: G4Profiler.hh:298