1 /*! 2 * \file mfront/src/BehaviourProfiler.cxx 3 * \brief 4 * \author Thomas Helfer 5 * \brief 15 mai 2014 6 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 7 * reserved. 8 * This project is publicly released under either the GNU GPL Licence 9 * or the CECILL-A licence. A copy of thoses licences are delivered 10 * with the sources of TFEL. CEA or EDF may also distribute this 11 * project under specific licensing conditions. 12 */ 13 14 #include<ctime> 15 #include<string> 16 #include<iterator> 17 #include <iomanip> 18 #include<iostream> 19 #include<algorithm> 20 #include<stdexcept> 21 #include "TFEL/Raise.hxx" 22 #include "MFront/BehaviourProfiler.hxx" 23 24 namespace mfront 25 { 26 27 #if !(defined _WIN32 || defined _WIN64) 28 /*! 29 * add a new measure 30 * t : measure to which the new measure is added 31 * start : start of the measure 32 * end : end of the measure 33 */ add_measure(std::atomic<intmax_t> & t,const timespec & start,const timespec & end)34 static inline void add_measure(std::atomic<intmax_t>& t, 35 const timespec& start, 36 const timespec& end) { 37 /* http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime */ 38 timespec temp; 39 if ((end.tv_nsec-start.tv_nsec)<0) { 40 temp.tv_sec = end.tv_sec-start.tv_sec-1; 41 temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; 42 } else { 43 temp.tv_sec = end.tv_sec-start.tv_sec; 44 temp.tv_nsec = end.tv_nsec-start.tv_nsec; 45 } 46 t += 1000000000*temp.tv_sec+temp.tv_nsec; 47 } // end of add_measure 48 #endif 49 50 /*! 51 * print a time to the specified stream 52 */ print_time(std::ostream & os,const intmax_t time)53 static void print_time(std::ostream& os, const intmax_t time) { 54 constexpr intmax_t musec_d = 1000; 55 constexpr intmax_t msec_d = 1000*musec_d; 56 constexpr intmax_t sec_d = msec_d*1000; 57 constexpr intmax_t min_d = sec_d*60; 58 constexpr intmax_t hour_d = min_d*60; 59 constexpr intmax_t days_d = hour_d*24; 60 intmax_t t = time; 61 const intmax_t ndays = t/days_d; 62 t -= ndays*days_d; 63 const intmax_t nhours = t/hour_d; 64 t -= nhours*hour_d; 65 const intmax_t nmins = t/min_d; 66 t -= nmins*min_d; 67 const intmax_t nsecs = t/sec_d; 68 t -= nsecs*sec_d; 69 const intmax_t nmsecs = t/msec_d; 70 t -= nmsecs*msec_d; 71 const intmax_t nmusecs = t/musec_d; 72 t -= nmusecs*musec_d; 73 if(ndays>0){ 74 os << ndays << "days "; 75 } 76 if(nhours>0){ 77 os << nhours << "hours "; 78 } 79 if(nmins>0){ 80 os << nmins << "mins "; 81 } 82 if(nsecs>0){ 83 os << nsecs << "secs "; 84 } 85 if(nmsecs>0){ 86 os << nmsecs << "msecs "; 87 } 88 if(nmusecs>0){ 89 os << nmusecs << "musecs "; 90 } 91 os << t << "nsecs"; 92 } // end pf print 93 getCodeBlockName(const unsigned int c)94 static std::string getCodeBlockName(const unsigned int c) { 95 auto n = std::string{}; 96 switch(c){ 97 case BehaviourProfiler::FLOWRULE: 98 n = "FlowRule"; 99 break; 100 case BehaviourProfiler::BEFOREINITIALIZELOCALVARIABLES: 101 n = "Init::BeforeInitializeLocalVariables"; 102 break; 103 case BehaviourProfiler::INITIALIZELOCALVARIABLES: 104 n = "Init::InitializeLocalVariables"; 105 break; 106 case BehaviourProfiler::AFTERINITIALIZELOCALVARIABLES: 107 n = "Init::AfterInitializeLocalVariables"; 108 break; 109 case BehaviourProfiler::COMPUTEPREDICTOR: 110 n = "Init::ComputePredictor"; 111 break; 112 case BehaviourProfiler::INITIALIZEJACOBIAN: 113 n = "Init::InitializeJacobian"; 114 break; 115 case BehaviourProfiler::COMPUTEPREDICTIONOPERATOR: 116 n = "ComputePredictionOperator"; 117 break; 118 case BehaviourProfiler::INTEGRATOR: 119 n = "Integrator"; 120 break; 121 case BehaviourProfiler::COMPUTETHERMODYNAMICFORCES: 122 n = "Integrator::ComputeThermodynamicForces"; 123 break; 124 case BehaviourProfiler::ADDITIONALCONVERGENCECHECKS: 125 n = "Integrator::AdditionalConvergenceChecks"; 126 break; 127 case BehaviourProfiler::COMPUTEDERIVATIVE: 128 n = "Integrator::ComputeDerivative"; 129 break; 130 case BehaviourProfiler::COMPUTEFDF: 131 n = "Integrator::ComputeFdF"; 132 break; 133 case BehaviourProfiler::TINYMATRIXSOLVE: 134 n = "Integrator::TinyMatrixSolve"; 135 break; 136 case BehaviourProfiler::COMPUTEFINALTHERMODYNAMICFORCES: 137 n = "ComputeFinalThermodynamicForces"; 138 break; 139 case BehaviourProfiler::COMPUTETANGENTOPERATOR: 140 n = "ComputeTangentOperator"; 141 break; 142 case BehaviourProfiler::APRIORITIMESTEPSCALINGFACTOR: 143 n = "APrioriTimeStepScalingFactor"; 144 break; 145 case BehaviourProfiler::APOSTERIORITIMESTEPSCALINGFACTOR: 146 n = "APosterioriTimeStepScalingFactor"; 147 break; 148 case BehaviourProfiler::UPDATEAUXILIARYSTATEVARIABLES: 149 n = "UpdateAuxiliaryStateVariables"; 150 break; 151 case BehaviourProfiler::FINITESTRAINPREPROCESSING: 152 n = "FiniteStrainPreProcessing"; 153 break; 154 case BehaviourProfiler::FINITESTRAINPOSTPROCESSING: 155 n = "FiniteStrainPostProcessing"; 156 break; 157 case BehaviourProfiler::USERDEFINEDCODE1: 158 n = "UserDefinedCode-1"; 159 break; 160 case BehaviourProfiler::USERDEFINEDCODE2: 161 n = "UserDefinedCode-2"; 162 break; 163 case BehaviourProfiler::TOTALTIME: 164 n = "TotalTime"; 165 break; 166 default: 167 tfel::raise("getCodeBlockName : no name associated " 168 "with the given code block"); 169 } 170 return n; 171 } 172 Timer(BehaviourProfiler & t,const unsigned short cn)173 BehaviourProfiler::Timer::Timer(BehaviourProfiler& t, const unsigned short cn) 174 : gtimer(t), c(cn) { 175 #if !(defined _WIN32 || defined _WIN64) 176 ::clock_gettime(CLOCK_THREAD_CPUTIME_ID,&(this->start)); 177 #endif 178 } // end of BehaviourProfiler::Timer 179 ~Timer()180 BehaviourProfiler::Timer::~Timer() { 181 #if !(defined _WIN32 || defined _WIN64) 182 ::clock_gettime(CLOCK_THREAD_CPUTIME_ID,&(this->end)); 183 add_measure(this->gtimer.measures[this->c],this->start,this->end); 184 #endif 185 } // end of BehaviourProfiler::~Timer 186 BehaviourProfiler(const std::string & n)187 BehaviourProfiler::BehaviourProfiler(const std::string& n) : name(n) { 188 std::fill(begin(measures),end(measures),0); 189 } // end of BehaviourProfiler::BehaviourProfiler 190 ~BehaviourProfiler()191 BehaviourProfiler::~BehaviourProfiler() { 192 using size_type = std::array<std::atomic<std::intmax_t>, 23>::size_type; 193 std::cout << "\nResults of " << this->name << " profiling : "; 194 print_time(std::cout,measures.back()); 195 std::cout << '\n'; 196 std::string::size_type w{0}; 197 for(size_type i=0;i+1!=measures.size();++i){ 198 if(measures[i]!=0){ 199 w = std::max(w, getCodeBlockName(i).size()); 200 } 201 } 202 for(size_type i=0;i+1!=measures.size();++i){ 203 if(measures[i]!=0){ 204 std::cout << "- " << std::setw(w) << std::left << getCodeBlockName(i) 205 << " : "; 206 print_time(std::cout,measures[i]); 207 std::cout << " (" << measures[i] << " ns)\n"; 208 } 209 } 210 std::cout << std::endl; 211 } // end of BehaviourProfiler::~BehaviourProfiler 212 213 } // end of namespace mfront 214