diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 56fb0c12..eb0dd06d 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -85,8 +85,7 @@ namespace ngcore for(auto & ltask : tasks) for(auto & task : ltask) { - task.start_time -= start_time; - task.stop_time -= start_time; + task.time -= start_time; } for(auto & job : jobs) { @@ -635,23 +634,31 @@ namespace ngcore value_id = job_task_map[jobs[t.id-1].type]; if(trace_thread_counter) { - paje.AddVariable( t.start_time, variable_type_active_threads, container_jobs, 1.0 ); - paje.SubVariable( t.stop_time, variable_type_active_threads, container_jobs, 1.0 ); + if(t.is_start) + paje.AddVariable( t.time, variable_type_active_threads, container_jobs, 1.0 ); + else + paje.SubVariable( t.time, variable_type_active_threads, container_jobs, 1.0 ); } if(trace_threads) { - paje.PushState( t.start_time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, true ); - paje.PopState( t.stop_time, state_type_task, thread_aliases[t.thread_id] ); + if(t.is_start) + paje.PushState( t.time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, true ); + else + paje.PopState( t.time, state_type_task, thread_aliases[t.thread_id] ); } break; case Task::ID_TIMER: value_id = timer_aliases[t.id]; - paje.PushState( t.start_time, state_type_timer, thread_aliases[t.thread_id], value_id, t.additional_value, true ); - paje.PopState( t.stop_time, state_type_timer, thread_aliases[t.thread_id] ); + if(t.is_start) + paje.PushState( t.time, state_type_timer, thread_aliases[t.thread_id], value_id, t.additional_value, true ); + else + paje.PopState( t.time, state_type_timer, thread_aliases[t.thread_id] ); break; default: - paje.PushState( t.start_time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, false ); - paje.PopState( t.stop_time, state_type_task, thread_aliases[t.thread_id] ); + if(t.is_start) + paje.PushState( t.time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, false ); + else + paje.PopState( t.time, state_type_task, thread_aliases[t.thread_id] ); break; } } diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index 5444a96c..c85c040f 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -79,8 +79,8 @@ namespace ngcore int additional_value; - TTimePoint start_time; - TTimePoint stop_time; + TTimePoint time; + bool is_start; static constexpr int ID_NONE = -1; static constexpr int ID_JOB = 1; @@ -178,23 +178,16 @@ namespace ngcore if(unlikely(tasks[thread_id].size() == max_num_events_per_thread)) StopTracing(); int task_num = tasks[thread_id].size(); - tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter()} ); + tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter(), true} ); return task_num; } - void StopTask(int thread_id, int task_num) + void StopTask(int thread_id, int id, int id_type = Task::ID_NONE) { if(!trace_threads && !trace_thread_counter) return; - if(task_num>=0) - tasks[thread_id][task_num].stop_time = GetTimeCounter(); + tasks[thread_id].push_back( Task{thread_id, id, id_type, 0, GetTimeCounter(), false} ); } - void SetTask(int thread_id, int task_num, int additional_value) { - if(!trace_threads && !trace_thread_counter) return; - if(task_num>=0) - tasks[thread_id][task_num].additional_value = additional_value; - } - void StartJob(int job_id, const std::type_info & type) { if(!tracing_enabled) return; diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index 294928d3..0b647d82 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -148,38 +148,95 @@ namespace ngcore }; + struct TNoTracing{ static constexpr bool do_tracing=false; }; + struct TTracing{ static constexpr bool do_tracing=true; }; - class NGCORE_API Timer + struct TNoTiming{ static constexpr bool do_timing=false; }; + struct TTiming{ static constexpr bool do_timing=true; }; + + namespace detail { + + template + constexpr bool is_tracing_type_v = std::is_same_v || std::is_same_v; + + template + constexpr bool is_timing_type_v = std::is_same_v || std::is_same_v; + } + + static TNoTracing NoTracing; + static TNoTiming NoTiming; + + template + class Timer { int timernr; - int priority; - public: - Timer (const std::string & name, int apriority = 1) - : priority(apriority) + int Init( const std::string & name ) { - timernr = NgProfiler::CreateTimer (name); + return NgProfiler::CreateTimer (name); } + public: + static constexpr bool do_tracing = TTracing::do_tracing; + static constexpr bool do_timing = TTiming::do_timing; + + Timer (const std::string & name) : timernr(Init(name)) { } + + template, bool> = false> + Timer( const std::string & name, TTracing ) : timernr(Init(name)) { } + + template, bool> = false> + Timer( const std::string & name, TTiming ) : timernr(Init(name)) { } + + Timer( const std::string & name, TTracing, TTiming ) : timernr(Init(name)) { } + void SetName (const std::string & name) { NgProfiler::SetName (timernr, name); } - void Start () + void Start () const { - if (priority <= 2) - NgProfiler::StartTimer (timernr); - if (priority <= 1) - if(trace) trace->StartTimer(timernr); + Start(TaskManager::GetThreadId()); } - void Stop () + void Stop () const { - if (priority <= 2) - NgProfiler::StopTimer (timernr); - if (priority <= 1) - if(trace) trace->StopTimer(timernr); + Stop(TaskManager::GetThreadId()); + } + void Start (int tid) const + { + if(tid==0) + { + if constexpr(do_timing) + NgProfiler::StartTimer (timernr); + if constexpr(do_tracing) + if(trace) trace->StartTimer(timernr); + } + else + { + if constexpr(do_timing) + NgProfiler::StartThreadTimer(timernr, tid); + if constexpr(do_tracing) + if(trace) trace->StartTask (tid, timernr, PajeTrace::Task::ID_TIMER); + } + } + void Stop (int tid) const + { + if(tid==0) + { + if constexpr(do_timing) + NgProfiler::StopTimer (timernr); + if constexpr(do_tracing) + if(trace) trace->StopTimer(timernr); + } + else + { + if constexpr(do_timing) + NgProfiler::StopThreadTimer(timernr, tid); + if constexpr(do_tracing) + if(trace) trace->StopTask (tid, timernr, PajeTrace::Task::ID_TIMER); + } } void AddFlops (double aflops) { - if (priority <= 2) + if constexpr(do_timing) NgProfiler::AddFlops (timernr, aflops); } @@ -196,14 +253,21 @@ namespace ngcore Timer object. Start / stop timer at constructor / destructor. */ + template class RegionTimer { - Timer & timer; + const TTimer & timer; + int tid; public: /// start timer - RegionTimer (Timer & atimer) : timer(atimer) { timer.Start(); } + RegionTimer (const TTimer & atimer) : timer(atimer) + { + tid = TaskManager::GetThreadId(); + timer.Start(tid); + } + /// stop timer - ~RegionTimer () { timer.Stop(); } + ~RegionTimer () { timer.Stop(tid); } RegionTimer() = delete; RegionTimer(const RegionTimer &) = delete; @@ -212,29 +276,11 @@ namespace ngcore void operator=(RegionTimer &&) = delete; }; - class ThreadRegionTimer - { - size_t nr; - size_t tid; - public: - /// start timer - ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid) - { NgProfiler::StartThreadTimer(nr, tid); } - /// stop timer - ~ThreadRegionTimer () - { NgProfiler::StopThreadTimer(nr, tid); } - - ThreadRegionTimer() = delete; - ThreadRegionTimer(ThreadRegionTimer &&) = delete; - ThreadRegionTimer(const ThreadRegionTimer &) = delete; - void operator=(const ThreadRegionTimer &) = delete; - void operator=(ThreadRegionTimer &&) = delete; - }; - class RegionTracer { int nr; int thread_id; + int type; public: static constexpr int ID_JOB = PajeTrace::Task::ID_JOB; static constexpr int ID_NONE = PajeTrace::Task::ID_NONE; @@ -251,28 +297,26 @@ namespace ngcore : thread_id(athread_id) { if (trace) - nr = trace->StartTask (athread_id, region_id, id_type, additional_value); + trace->StartTask (athread_id, region_id, id_type, additional_value); + type = id_type; + nr = region_id; } /// start trace with timer - RegionTracer (int athread_id, Timer & timer, int additional_value = -1 ) + template + RegionTracer (int athread_id, TTimer & timer, int additional_value = -1 ) : thread_id(athread_id) { + nr = timer; + type = ID_TIMER; if (trace) - nr = trace->StartTask (athread_id, static_cast(timer), ID_TIMER, additional_value); + trace->StartTask (athread_id, nr, type, additional_value); } - /// set user defined value - void SetValue( int additional_value ) - { - if (trace) - trace->SetTask( thread_id, nr, additional_value ); - } - /// stop trace ~RegionTracer () { if (trace) - trace->StopTask (thread_id, nr); + trace->StopTask (thread_id, nr, type); } }; diff --git a/libsrc/core/taskmanager.cpp b/libsrc/core/taskmanager.cpp index 1d88b766..9274fb97 100644 --- a/libsrc/core/taskmanager.cpp +++ b/libsrc/core/taskmanager.cpp @@ -35,11 +35,7 @@ namespace ngcore int TaskManager :: num_threads = 1; - // #ifndef __clang__ thread_local int TaskManager :: thread_id = 0; - // #else - // __thread int TaskManager :: thread_id; - // #endif const function * TaskManager::func; const function * TaskManager::startup_function = nullptr; @@ -174,10 +170,12 @@ namespace ngcore num_threads = 1; } +#ifdef WIN32 int TaskManager :: GetThreadId() { return thread_id; } +#endif void TaskManager :: StartWorkers() { diff --git a/libsrc/core/taskmanager.hpp b/libsrc/core/taskmanager.hpp index 27de9090..8d2886b1 100644 --- a/libsrc/core/taskmanager.hpp +++ b/libsrc/core/taskmanager.hpp @@ -78,12 +78,11 @@ namespace ngcore - // #ifndef __clang__ +#ifdef WIN32 // no exported thread_local in dlls on Windows static thread_local int thread_id; - // #else - // static __thread int thread_id; - // #endif - +#else + NGCORE_API static thread_local int thread_id; +#endif NGCORE_API static bool use_paje_trace; public: @@ -102,11 +101,15 @@ namespace ngcore void ResumeWorkers() { sleep = false; } NGCORE_API static void SetNumThreads(int amax_threads); - NGCORE_API static int GetMaxThreads() { return max_threads; } + static int GetMaxThreads() { return max_threads; } // static int GetNumThreads() { return task_manager ? task_manager->num_threads : 1; } - NGCORE_API static int GetNumThreads() { return num_threads; } + static int GetNumThreads() { return num_threads; } +#ifdef WIN32 NGCORE_API static int GetThreadId(); - NGCORE_API int GetNumNodes() const { return num_nodes; } +#else + static int GetThreadId() { return thread_id; } +#endif + int GetNumNodes() const { return num_nodes; } static void SetPajeTrace (bool use) { use_paje_trace = use; }