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