Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:58:58

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // G4Profiler
0027 //
0028 // Class description:
0029 //
0030 // Class providing the internal profiling interface for Geant4.
0031 
0032 // Author: Jonathan Madsen, LBNL - November 2020
0033 // --------------------------------------------------------------------
0034 #ifndef G4Profiler_hh
0035 #define G4Profiler_hh 1
0036 
0037 // Fundamental definitions
0038 #ifndef G4GMAKE
0039 #  include "G4GlobalConfig.hh"
0040 #endif
0041 
0042 // for meta-programming stuff
0043 #include "G4Profiler.icc"
0044 
0045 #if defined(GEANT4_USE_TIMEMORY)
0046 #  include <timemory/utility/argparse.hpp>
0047 #endif
0048 
0049 #include "globals.hh"
0050 
0051 #include <cstddef>
0052 #include <functional>
0053 #include <string>
0054 #include <utility>
0055 #include <type_traits>
0056 #include <tuple>
0057 #include <vector>
0058 #include <array>
0059 
0060 //----------------------------------------------------------------------------//
0061 
0062 class G4Run;
0063 class G4Event;
0064 class G4Track;
0065 class G4Step;
0066 
0067 struct G4ProfileType
0068 {
0069   enum : size_t
0070   {
0071     Run = 0,
0072     Event,
0073     Track,
0074     Step,
0075     User,
0076     TypeEnd
0077   };
0078 };
0079 
0080 struct G4ProfileOp
0081 {
0082   enum : int
0083   {
0084     Query = 0,
0085     Label,
0086     Tool
0087   };
0088 };
0089 
0090 //----------------------------------------------------------------------------//
0091 
0092 class G4Profiler
0093 {
0094  public:
0095   using array_type = std::array<bool, G4ProfileType::TypeEnd>;
0096 
0097 #if defined(GEANT4_USE_TIMEMORY)
0098   using ArgumentParser = tim::argparse::argument_parser;
0099 #else
0100   struct ArgumentParser
0101   {
0102     explicit ArgumentParser(std::string) {}
0103   };
0104 #endif
0105 
0106   static void Configure(const std::vector<std::string>& args);
0107   static void Configure(int argc, char** argv);
0108   static void Configure(ArgumentParser&, const std::vector<std::string>& args);
0109   static void Configure(ArgumentParser&, int argc, char** argv);
0110   static void Finalize();
0111 
0112   static bool GetEnabled(size_t v) { return GetEnabled().at(v); }
0113   static void SetEnabled(size_t v, bool val) { GetEnabled().at(v) = val; }
0114 
0115   static bool GetPerEvent() { return GetPerEventImpl(); }
0116   static void SetPerEvent(bool val) { GetPerEventImpl() = val; }
0117 
0118  private:
0119   static array_type& GetEnabled();
0120   static bool& GetPerEventImpl()
0121   {
0122     static bool _value = false;
0123     return _value;
0124   }
0125 };
0126 
0127 //----------------------------------------------------------------------------//
0128 //  maps enumerations to types
0129 //
0130 template <size_t Category>
0131 struct G4ProfilerObject
0132 {
0133   using type = void;
0134 };
0135 
0136 template <size_t Category>
0137 using G4ProfilerObject_t = typename G4ProfilerObject<Category>::type;
0138 
0139 template <>
0140 struct G4ProfilerObject<G4ProfileType::Run>
0141 {
0142   using type = const G4Run*;
0143 };
0144 
0145 template <>
0146 struct G4ProfilerObject<G4ProfileType::Event>
0147 {
0148   using type = const G4Event*;
0149 };
0150 
0151 template <>
0152 struct G4ProfilerObject<G4ProfileType::Track>
0153 {
0154   using type = const G4Track*;
0155 };
0156 
0157 template <>
0158 struct G4ProfilerObject<G4ProfileType::Step>
0159 {
0160   using type = const G4Step*;
0161 };
0162 
0163 template <>
0164 struct G4ProfilerObject<G4ProfileType::User>
0165 {
0166   using type = const std::string&;
0167 };
0168 
0169 //----------------------------------------------------------------------------//
0170 // default set of profiler args
0171 template <size_t Category>
0172 struct G4ProfilerArgs
0173 {
0174   // this resolves to the G4ProfilerObject type-trait above, e.g.
0175   // "const G4Step*" when category is G4ProfileType::Step
0176   using value_type = G4ProfilerObject_t<Category>;
0177 
0178   // two-dimensional type-list where each inner type-list is a set
0179   // of arguments to support creating a profiler type from
0180   using type = G4TypeList<G4PROFILER_ARG_SET(value_type)>;
0181   // so above means there are functors in use which apply:
0182   //
0183   //  G4StepProfiler _profiler(const G4Step*);
0184   //
0185 };
0186 
0187 template <size_t Category>
0188 using G4ProfilerArgs_t = typename G4ProfilerArgs<Category>::type;
0189 
0190 //----------------------------------------------------------------------------//
0191 
0192 template <size_t Category, typename RetT, typename CommonT = G4CommonTypeList<>>
0193 struct G4ProfilerFunctors
0194 {
0195   using type = G4Impl::Functors_t<RetT, CommonT, G4ProfilerArgs_t<Category>>;
0196 };
0197 
0198 template <size_t Category, typename RetT, typename... CommonT>
0199 using G4ProfilerFunctors_t =
0200   typename G4ProfilerFunctors<Category, RetT,
0201                               G4CommonTypeList<CommonT...>>::type;
0202 
0203 //----------------------------------------------------------------------------//
0204 
0205 #ifdef GEANT4_USE_TIMEMORY
0206 
0207 // Pre-declare the timemory component that will be used
0208 namespace tim
0209 {
0210   namespace component
0211   {
0212     template <size_t, typename Tag>
0213     struct user_bundle;
0214   }  // namespace component
0215 
0216   template <typename... Types>
0217   class auto_tuple;
0218 
0219   template <typename Tag, typename... Types>
0220   class auto_bundle;
0221 }  // namespace tim
0222 
0223 namespace g4tim
0224 {
0225   using namespace tim;
0226   using tim::component::user_bundle;
0227 
0228   struct G4api : public tim::concepts::api
0229   {};
0230 
0231   using ProfilerArgparser = argparse::argument_parser;
0232 
0233 }  // namespace g4tim
0234 
0235 using G4RunProfiler   = g4tim::user_bundle<G4ProfileType::Run, G4ProfileType>;
0236 using G4EventProfiler = g4tim::user_bundle<G4ProfileType::Event, G4ProfileType>;
0237 using G4TrackProfiler = g4tim::user_bundle<G4ProfileType::Track, G4ProfileType>;
0238 using G4StepProfiler  = g4tim::user_bundle<G4ProfileType::Step, G4ProfileType>;
0239 using G4UserProfiler  = g4tim::user_bundle<G4ProfileType::User, G4ProfileType>;
0240 
0241 template <typename... Types>
0242 using G4ProfilerBundle = g4tim::auto_bundle<g4tim::G4api, Types...>;
0243 
0244 #else
0245 
0246 namespace g4tim
0247 {
0248   struct ProfilerArgparser
0249   {};
0250 
0251   /// this provides a dummy wrapper for the profiling
0252   template <typename... Types>
0253   struct handler
0254   {
0255     template <typename... Args>
0256     handler(Args&&...)
0257     {}
0258     ~handler() = default;
0259     handler(const handler&) = default;
0260     handler(handler&&) = default;
0261     handler& operator=(const handler&) = default;
0262     handler& operator=(handler&&) = default;
0263 
0264     void record() {}
0265     template <typename... Args>
0266     void start(Args&&...)
0267     {}
0268     template <typename... Args>
0269     void stop(Args&&...)
0270     {}
0271     void push() {}
0272     void pop() {}
0273     void reset() {}
0274     void report_at_exit(bool) {}
0275     template <typename... Args>
0276     void mark_begin(Args&&...)
0277     {}
0278     template <typename... Args>
0279     void mark_end(Args&&...)
0280     {}
0281     friend std::ostream& operator<<(std::ostream& os, const handler&)
0282     {
0283       return os;
0284     }
0285   };
0286 
0287   template <size_t Idx, typename Tp>
0288   struct user_bundle
0289   {
0290     template <typename... Args>
0291     user_bundle(Args&&...)
0292     {}
0293 
0294     template <typename... Types, typename... Args>
0295     static void configure(Args&&...)
0296     {}
0297 
0298     static void reset() {}
0299   };
0300 
0301 }  // namespace g4tim
0302 
0303 using G4RunProfiler = g4tim::handler<>;
0304 using G4EventProfiler = g4tim::handler<>;
0305 using G4TrackProfiler = g4tim::handler<>;
0306 using G4StepProfiler = g4tim::handler<>;
0307 using G4UserProfiler = g4tim::handler<>;
0308 
0309 template <typename... Types>
0310 using G4ProfilerBundle = g4tim::handler<Types...>;
0311 
0312 #endif
0313 
0314 //----------------------------------------------------------------------------//
0315 
0316 /// @brief G4ProfilerConfig
0317 /// This class is used to determine whether to activate profiling in the code
0318 ///
0319 /// @example extended/parallel/ThreadsafeScorers/ts_scorers.cc
0320 /// The main for this file contains an example for configuring the G4Profiler
0321 /// for G4Track and G4Step
0322 ///
0323 template <size_t Category>
0324 class G4ProfilerConfig
0325 {
0326  public:
0327   using type = G4ProfilerBundle<g4tim::user_bundle<Category, G4ProfileType>>;
0328   using this_type = G4ProfilerConfig<Category>;
0329 
0330   static constexpr size_t arg_sets =
0331     G4TypeListSize<G4ProfilerArgs_t<Category>>::value;
0332 
0333   using QueryFunc_t = G4ProfilerFunctors_t<Category, bool>;
0334   using LabelFunc_t = G4ProfilerFunctors_t<Category, std::string>;
0335   using ToolFunc_t  = std::tuple<std::function<type*(const std::string&)>>;
0336 
0337  public:
0338   // when constructed with no args, should call operator()
0339   G4ProfilerConfig() = default;
0340 
0341   // constructor calls Query(...), Label(...), Tool(...)
0342   template <typename Arg, typename... Args>
0343   G4ProfilerConfig(Arg, Args...);
0344 
0345   // will delete m_bundle is allocated
0346   ~G4ProfilerConfig();
0347 
0348   // default the move-constructor and move-assignment
0349   G4ProfilerConfig(G4ProfilerConfig&&) = default;
0350   G4ProfilerConfig& operator=(G4ProfilerConfig&&) = default;
0351 
0352   // do not allow copy-construct and copy-assign bc of raw pointer
0353   G4ProfilerConfig(const G4ProfilerConfig&) = delete;
0354   G4ProfilerConfig& operator=(const G4ProfilerConfig&) = delete;
0355 
0356   // if constructed without args, this function should be called
0357   template <typename... Args>
0358   bool operator()(Args...);
0359 
0360   // provide nullptr check
0361   operator bool() const { return (m_bundle != nullptr); }
0362 
0363  private:
0364   type* m_bundle = nullptr;
0365 
0366   static QueryFunc_t& GetQueries()
0367   {
0368     static QueryFunc_t _value;
0369     return _value;
0370   }
0371 
0372   static LabelFunc_t& GetLables()
0373   {
0374     static LabelFunc_t _value;
0375     return _value;
0376   }
0377 
0378   static ToolFunc_t& GetTools()
0379   {
0380     static ToolFunc_t _value;
0381     return _value;
0382   }
0383 
0384  public:
0385   // invokes the functor that determines whether to enable profiling
0386   template <typename... Args>
0387   static bool Query(Args... _args);
0388 
0389   // invokes the functor for generating a Label when profiling is enabled
0390   template <typename... Args>
0391   static std::string Label(Args... _args);
0392 
0393   // invokes the functor for configuring a Tool instance
0394   template <typename... Args>
0395   static type* Tool(const std::string&);
0396 
0397   using QueryHandler_t = FuncHandler<this_type, QueryFunc_t, bool>;
0398   using LabelHandler_t = FuncHandler<this_type, LabelFunc_t, std::string>;
0399   using ToolHandler_t  = FuncHandler<this_type, ToolFunc_t, type*>;
0400 
0401   static QueryHandler_t GetQueryFunctor();
0402   static QueryHandler_t GetFallbackQueryFunctor();
0403 
0404   static LabelHandler_t GetLabelFunctor();
0405   static LabelHandler_t GetFallbackLabelFunctor();
0406 
0407   static ToolHandler_t GetToolFunctor();
0408   static ToolHandler_t GetFallbackToolFunctor();
0409 
0410  private:
0411   template <bool B, typename Lhs, typename Rhs>
0412   using conditional_t = typename std::conditional<B, Lhs, Rhs>::type;
0413 
0414   // this provides the global statics for the functors
0415   template <int Idx>
0416   struct PersistentSettings
0417   {
0418     // determine the functor type
0419     using functor_type = conditional_t<
0420       Idx == G4ProfileOp::Query, QueryFunc_t,
0421       conditional_t<Idx == G4ProfileOp::Label, LabelFunc_t, ToolFunc_t>>;
0422 
0423     PersistentSettings()  = default;
0424     ~PersistentSettings() = default;
0425     // default member initialization
0426     functor_type m_functor;
0427   };
0428 
0429   template <int Idx>
0430   static PersistentSettings<Idx>& GetPersistentFallback();
0431 
0432   template <int Idx>
0433   static PersistentSettings<Idx>& GetPersistent();
0434 };
0435 
0436 //----------------------------------------------------------------------------//
0437 
0438 // alias for getting type
0439 template <size_t Category>
0440 using G4ProfilerConfig_t = typename G4ProfilerConfig<Category>::type;
0441 
0442 // ----------------------------------------------------------------------
0443 
0444 template <size_t Cat>
0445 template <typename Arg, typename... Args>
0446 G4ProfilerConfig<Cat>::G4ProfilerConfig(Arg _arg, Args... _args)
0447 {
0448   this->operator()(_arg, _args...);
0449 }
0450 
0451 // ----------------------------------------------------------------------
0452 
0453 template <size_t Cat>
0454 template <typename... Args>
0455 bool G4ProfilerConfig<Cat>::operator()(Args... _args)
0456 {
0457   if(Query(_args...))
0458   {
0459     m_bundle = Tool(Label(_args...));
0460     if(m_bundle)
0461       m_bundle->start(_args...);
0462     return (m_bundle != nullptr);
0463   }
0464   return false;
0465 }
0466 
0467 // ----------------------------------------------------------------------
0468 
0469 // invokes the functor that determines whether to enable profiling
0470 template <size_t Cat>
0471 template <typename... Args>
0472 bool G4ProfilerConfig<Cat>::Query(Args... _args)
0473 {
0474   return QueryHandler_t{ GetPersistent<G4ProfileOp::Query>().m_functor }(
0475     _args...);
0476 }
0477 
0478 //----------------------------------------------------------------------------//
0479 
0480 // invokes the functor for generating a label when profiling is enabled
0481 template <size_t Cat>
0482 template <typename... Args>
0483 std::string G4ProfilerConfig<Cat>::Label(Args... _args)
0484 {
0485   return LabelHandler_t{ GetPersistent<G4ProfileOp::Label>().m_functor }(
0486     _args...);
0487 }
0488 
0489 //----------------------------------------------------------------------------//
0490 
0491 // invokes the functor for configuring a tool instance
0492 template <size_t Cat>
0493 template <typename... Args>
0494 typename G4ProfilerConfig<Cat>::type* G4ProfilerConfig<Cat>::Tool(
0495   const std::string& _args)
0496 {
0497   return ToolHandler_t{ GetPersistent<G4ProfileOp::Tool>().m_functor }(_args);
0498 }
0499 
0500 //----------------------------------------------------------------------------//
0501 
0502 // ensure that any implicit instantiations of the G4ProfilerConfig
0503 // are not done in another translation units because we will
0504 // explicitly instantiate G4ProfilerConfig in the .cc file
0505 
0506 // line breaks make this much harder to read
0507 // clang-format off
0508 extern template class G4ProfilerConfig<G4ProfileType::Run>;
0509 extern template class G4ProfilerConfig<G4ProfileType::Event>;
0510 extern template class G4ProfilerConfig<G4ProfileType::Track>;
0511 extern template class G4ProfilerConfig<G4ProfileType::Step>;
0512 extern template class G4ProfilerConfig<G4ProfileType::User>;
0513 extern template G4ProfilerConfig<G4ProfileType::Run>::G4ProfilerConfig(const G4Run*);
0514 extern template G4ProfilerConfig<G4ProfileType::Event>::G4ProfilerConfig(const G4Event*);
0515 extern template G4ProfilerConfig<G4ProfileType::Track>::G4ProfilerConfig(const G4Track*);
0516 extern template G4ProfilerConfig<G4ProfileType::Step>::G4ProfilerConfig(const G4Step*);
0517 extern template G4ProfilerConfig<G4ProfileType::User>::G4ProfilerConfig(const std::string&);
0518 // clang-format on
0519 
0520 //----------------------------------------------------------------------------//
0521 
0522 #ifndef GEANT4_USE_TIMEMORY
0523 
0524 #  include <ostream>
0525 #  include <string>
0526 
0527 #endif
0528 
0529 #if defined(GEANT4_USE_TIMEMORY)
0530 // two macros below create a unique variable name based on the line number
0531 #  define G4USER_PROFILER_VAR_JOIN(X, Y) X##Y
0532 #  define G4USER_PROFILER_VAR(Y) G4USER_PROFILER_VAR_JOIN(g4user_profiler_, Y)
0533 
0534 // inserts just the string
0535 #  define G4USER_SCOPED_PROFILE(...)                                           \
0536     G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)(       \
0537       TIMEMORY_JOIN("", __VA_ARGS__))
0538 
0539 // inserts the function
0540 #  define G4USER_SCOPED_PROFILE_FUNC(...)                                      \
0541     G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)(       \
0542       TIMEMORY_JOIN("", __FUNCTION__, "/", __VA_ARGS__))
0543 
0544 // inserts the function and file
0545 #  define G4USER_SCOPED_PROFILE_FUNC_FILE(...)                                 \
0546     G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)(       \
0547       TIMEMORY_JOIN("", __FUNCTION__, '@', __FILE__, '/', __VA_ARGS__))
0548 
0549 // inserts the function, file, and line number
0550 #  define G4USER_SCOPED_PROFILE_FUNC_FILE_LINE(...)                            \
0551     G4ProfilerConfig<G4ProfileType::User> G4USER_PROFILER_VAR(__LINE__)(       \
0552       TIMEMORY_JOIN("", __FUNCTION__, '@', __FILE__, ':', __LINE__, '/',       \
0553                     __VA_ARGS__))
0554 #else
0555 #  define G4USER_SCOPED_PROFILE(...)
0556 #  define G4USER_SCOPED_PROFILE_FUNC(...)
0557 #  define G4USER_SCOPED_PROFILE_FUNC_FILE(...)
0558 #  define G4USER_SCOPED_PROFILE_FUNC_FILE_LINE(...)
0559 #endif
0560 
0561 #endif  // G4Profiler_hh