Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
251 /// this provides a dummy wrapper for the profiling
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
316/// @brief G4ProfilerConfig
317/// This class is used to determine whether to activate profiling in the code
318///
319/// @example extended/parallel/ThreadsafeScorers/ts_scorers.cc
320/// The main for this file contains an example for configuring the G4Profiler
321/// for G4Track and G4Step
322///
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
366 static QueryFunc_t& GetQueries()
367 {
368 static QueryFunc_t _value;
369 return _value;
370 }
371
372 static LabelFunc_t& GetLables()
373 {
374 static LabelFunc_t _value;
375 return _value;
376 }
377
378 static ToolFunc_t& GetTools()
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>
416 struct PersistentSettings
417 {
418 // determine the functor type
419 using functor_type = conditional_t<
421 conditional_t<Idx == G4ProfileOp::Label, LabelFunc_t, ToolFunc_t>>;
422
423 PersistentSettings() = default;
424 ~PersistentSettings() = default;
425 // default member initialization
426 functor_type m_functor;
427 };
428
429 template <int Idx>
430 static PersistentSettings<Idx>& GetPersistentFallback();
431
432 template <int Idx>
433 static PersistentSettings<Idx>& GetPersistent();
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
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
FuncHandler< this_type, LabelFunc_t, std::string > LabelHandler_t
Definition: G4Profiler.hh:398
static QueryHandler_t GetFallbackQueryFunctor()
Definition: G4Profiler.cc:446
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 ToolHandler_t GetToolFunctor()
Definition: G4Profiler.cc:436
bool operator()(Args...)
Definition: G4Profiler.hh:455
static ToolHandler_t GetFallbackToolFunctor()
Definition: G4Profiler.cc:468
G4ProfilerConfig(const G4ProfilerConfig &)=delete
static constexpr size_t arg_sets
Definition: G4Profiler.hh:330
G4ProfilerConfig & operator=(const G4ProfilerConfig &)=delete
static QueryHandler_t GetQueryFunctor()
Definition: G4Profiler.cc:418
G4ProfilerBundle< g4tim::user_bundle< Category, G4ProfileType > > type
Definition: G4Profiler.hh:327
G4ProfilerFunctors_t< Category, std::string > LabelFunc_t
Definition: G4Profiler.hh:334
static type * Tool(const std::string &)
Definition: G4Profiler.hh:494
static bool Query(Args... _args)
Definition: G4Profiler.hh:472
static LabelHandler_t GetLabelFunctor()
Definition: G4Profiler.cc:427
G4ProfilerConfig(G4ProfilerConfig &&)=default
static LabelHandler_t GetFallbackLabelFunctor()
Definition: G4Profiler.cc:457
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
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
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