1 #include <mutex>
2 
3 #include "profiler.hpp"
4 
5 namespace ngcore
6 {
7   std::vector<NgProfiler::TimerVal> NgProfiler::timers(NgProfiler::SIZE); // NOLINT
8 
9   std::string NgProfiler::filename;
10 
11   std::array<size_t,NgProfiler::SIZE> NgProfiler::dummy_thread_times;
12   size_t * NgProfiler::thread_times = NgProfiler::dummy_thread_times.data(); // NOLINT
13   std::array<size_t,NgProfiler::SIZE> NgProfiler::dummy_thread_flops;
14   size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops.data(); // NOLINT
15 
16   std::shared_ptr<Logger> NgProfiler::logger = GetLogger("Profiler"); // NOLINT
17 
NgProfiler()18   NgProfiler :: NgProfiler()
19   {
20     for (auto & t : timers)
21     {
22         t.tottime = 0.0;
23         t.usedcounter = 0;
24         t.flops = 0.0;
25     }
26   }
27 
~NgProfiler()28   NgProfiler :: ~NgProfiler()
29   {
30     if (filename.length())
31       {
32         logger->debug( "write profile to file {}", filename );
33         FILE *prof = fopen(filename.c_str(),"w"); // NOLINT
34         Print (prof);
35         fclose(prof); // NOLINT
36       }
37 
38     if (getenv ("NGPROFILE"))
39       {
40        std::string filename = "netgen.prof";
41 #ifdef PARALLEL
42        filename += "."+ToString(id);
43 #endif
44        if (id == 0) logger->info( "write profile to file {}", filename );
45        FILE *prof = fopen(filename.c_str(),"w"); // NOLINT
46        Print (prof);
47        fclose(prof); // NOLINT
48       }
49   }
50 
Print(FILE * prof)51   void NgProfiler :: Print (FILE * prof)
52   {
53     int i = 0;
54     for (auto & t : timers)
55     {
56       if (t.count != 0 || t.usedcounter != 0)
57         {
58           fprintf(prof,"job %3i calls %8li, time %6.4f sec",i,t.count,t.tottime); // NOLINT
59           if(t.flops != 0.0)
60             fprintf(prof,", MFlops = %6.2f",t.flops / (t.tottime) * 1e-6); // NOLINT
61           if(t.loads != 0.0)
62             fprintf(prof,", MLoads = %6.2f",t.loads / (t.tottime) * 1e-6); // NOLINT
63           if(t.stores != 0.0)
64             fprintf(prof,", MStores = %6.2f",t.stores / (t.tottime) * 1e-6); // NOLINT
65           if(t.usedcounter)
66             fprintf(prof," %s",t.name.c_str()); // NOLINT
67           fprintf(prof,"\n"); // NOLINT
68         }
69       i++;
70     }
71   }
72 
73 
CreateTimer(const std::string & name)74   int NgProfiler :: CreateTimer (const std::string & name)
75   {
76     static std::mutex createtimer_mutex;
77     int nr = -1;
78     {
79       std::lock_guard<std::mutex> guard(createtimer_mutex);
80       for (int i = SIZE-1; i > 0; i--)
81       {
82         auto & t = timers[i];
83         if (!t.usedcounter)
84           {
85             t.usedcounter = 1;
86             t.name = name;
87             nr = i;
88             break;
89           }
90       }
91     }
92     if (nr > -1) return nr;
93     static bool first_overflow = true;
94     if (first_overflow)
95       {
96         first_overflow = false;
97         NgProfiler::logger->warn("no more timer available, reusing last one");
98       }
99     return 0;
100   }
101 
Reset()102   void NgProfiler :: Reset ()
103   {
104       for(auto & t : timers)
105       {
106           t.tottime = 0.0;
107           t.count = 0;
108           t.flops = 0.0;
109           t.loads = 0;
110           t.stores = 0;
111       }
112   }
113 
114   NgProfiler prof; // NOLINT
115 
116 #ifdef NETGEN_TRACE_MEMORY
117   std::vector<std::string> MemoryTracer::names{"all"};
118   std::vector<int> MemoryTracer::parents{-1};
119 #endif // NETGEN_TRACE_MEMORY
120 
121 } // namespace ngcore
122