/* DFT++ is a density functional package developed by the research group of Professor Tomas Arias Copyright 1996-2003 Sohrab Ismail-Beigi This file is part of DFT++. DFT++ is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. DFT++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DFT++; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Please see the file CREDITS for a list of authors. For academic users, we request that publications using results obtained with this software reference "New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000). and, if using the wavelet basis, further reference "Multiresolution analysis of electronic structure: semicardinal and wavelet bases," T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999). and "Robust ab initio calculation of condensed matter: transparent convergence through semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003). For your convenience, preprints of the above articles may be obtained from http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively. */ /************************************************************************/ /* */ /* Tairan Wang Nov. 6, 1997 */ /* */ /* A set of timer access routines for MPI performance profiling */ /* */ /************************************************************************/ /* $Id: timer.cpp,v 1.14.2.4 2003/05/29 18:54:35 ivan Exp $ */ #include "header.h" #include "parallel.h" #ifdef DFT_PROFILING #define ON 1 #define OFF 0 #define NUM_TIMERS 64 #define NUM_COUNTERS 64 int timerState[NUM_TIMERS]; char timerTitle[NUM_TIMERS][DFT_MSG_LEN]; double lastStart[NUM_TIMERS],accTime[NUM_TIMERS]; int num_timers; double counterState[NUM_COUNTERS]; char counterTitle[NUM_TIMERS][DFT_MSG_LEN]; int num_counters; ////////////////////////////////////////////////////////////////// /* To turn on a timer. Returns the prior state of the timer. */ int timerOn(int timer) { int priorState = timerState[timer]; if (priorState == OFF) { timerState[timer] = ON; lastStart[timer] = System::get_time(); } // SIB 27/1/00: commented out for now... this is NOT thread safe // i.e. when running threads, many threads // call the same timer at the same time, and as // variables are global, we get WARNINGs galore // else // { // dft_log("\nWARNING: timer %d already on at:%f", // timer,lastStart[timer]); // } return(priorState); } /* To turn a timer off. Again, returns the prior state. */ int timerOff(int timer) { int priorState = timerState[timer]; if (priorState == ON) { timerState[timer] = OFF; accTime[timer] += System::get_time() - lastStart[timer]; } return(priorState); } /* To set the timer to a given state. Returns prior state. */ int timerSetState(int timer, int state) { if (state == ON) return timerOn(timer); else return timerOff(timer); } /* To initialize all timers. */ void timerInitAll(void) { num_timers = 0; for (int i = 0; i < NUM_TIMERS; i++) timerInit(i); } /* To initialize a timer. */ void timerInit(int timer, char* title) { timerState[timer] = OFF; accTime[timer] = 0; strcpy(timerTitle[timer], title); if ((timer+1) > num_timers) num_timers = timer+1; } void timerInit(int timer) { timerState[timer] = OFF; accTime[timer] = 0; } /* To reset a timer, possibly running. */ int timerReset(int timer) { int priorState = timerOff(timer); timerInit(timer); timerSetState(timer,priorState); return(priorState); } /* To read a timer, regardless of state. */ double timerRead(int timer) { double timeTemp; timeTemp = accTime[timer]; if (timerState[timer] == ON) timeTemp += System::get_time() - lastStart[timer]; return(timeTemp); } /* To get the title of a timer */ char * timerGetTitle(int timer) { return (timerTitle[timer]); } /* To get the number of initialized timers */ int timerGetTotal(void) { return num_timers; } /* * Convenience routines to turn on all the timers */ int timerActivateAll(void) { timerInitAll(); timerInit(0, "Initializations"); timerInit(1, "Total computation"); timerInit(2, "Minimization routines"); timerInit(3, "Y1^Y2"); timerInit(4, "Y*M"); timerInit(5, "Column bundle transpose"); timerInit(6, "diagouterI"); timerInit(7, "diaginner"); timerInit(8, "memory allocation"); timerInit(9, "do_linmin"); timerInit(10, "calc_elecgrad_Hsub"); timerInit(11, "calc_UVCn_d_elec_dependent_e"); timerInit(12, "Y1^Y2 MPI_Allreduce"); timerInit(13, "Other MPI_Allreduce"); timerInit(14, "\tcalc_U"); timerInit(15, "\tcalc_C"); timerInit(16, "\tcalc_n"); timerInit(17, "\tsolve_poisson"); timerInit(18, "\tcalc_KE"); timerInit(19, "\tcalc_Eloc"); timerInit(20, "\tcalc_Enl"); timerInit(21, "\tcalc_EH"); timerInit(22, "\tcalc_Exc"); timerInit(23, "\tcalc_Ecore"); timerInit(24, "\tcalc_Eewald"); timerInit(25, "\tcalc_Vscloc"); timerInit(26, "\tapply_Hsp"); timerInit(27, "\tdiagonalize_herm"); timerInit(28, "\tmatrix*matrix"); timerInit(29, "\tO"); timerInit(30, "\tPbar"); timerInit(31, "\tL"); timerInit(32, "\tinvL"); timerInit(33, "\tprecond"); timerInit(34, "\tI"); timerInit(35, "\tJ"); timerInit(36, "\tIdag"); timerInit(37, "\tJdag"); timerInit(38,"diaginner MPI_Allreduce"); timerInit(39,"diagouterI MPI_Allreduce"); timerInit(40,"FFT3D"); timerInit(41,"calc_V"); timerInit(42,"apply_Hsp_loc"); timerInit(43,"apply_Hsp_nloc"); timerInit(50,"operator \"=\""); timerInit(51,"operator \"+\""); timerInit(52,"operator \"-\""); // For wavelet profiling, it's important to count the time we spend doing // data conversion. #ifdef WAVELETS timerInit(60,"GetRe, PutRe, GetIm, PutIm"); #endif // WAVELETS return 43; } /* * Report the timer content */ void timerReport(int iter) { int itimer, n_timers = timerGetTotal(); if (n_timers > 0) { dft_log("\nTiming reports at iteration %d:\n",iter); for (itimer = 0; itimer < n_timers; itimer++) dft_log("\t%4d %s :\t\t%f sec\n", itimer, timerGetTitle(itimer), timerRead(itimer)); dft_log("\n"); dft_log_flush(); } } /* * Report the timer content and counter content: */ void timer_counter_Report(int iter) { timerReport(iter); counterReport(iter); } ///////////////////////////////////////////////////////////////// void counterReport(int iter) { int n_counters = counterGetTotal(); if (n_counters > 0) { dft_log("\nCounter reports at iteration %d:\n",iter); for (int icounter = 0; icounter < n_counters; icounter++) if (counterRead(icounter)>1.0e6) dft_log("\t%4d %s :\t\t%e\n", icounter, counterGetTitle(icounter), counterRead(icounter)); else dft_log("\t%4d %s :\t\t%f\n", icounter, counterGetTitle(icounter), counterRead(icounter)); dft_log("\n"); dft_log_flush(); } } int counterActivateAll(void) { counterInitAll(); counterInit(0, "Y1^Y2 flop count"); counterInit(1, "Y1^Y2 total count"); counterInit(2, "Y1^Y2 distributed count"); counterInit(3, "Y1^Y2 MPI_Allreduce bytes"); counterInit(4, "Y*M flop count"); counterInit(5, "Y*M total count"); counterInit(6, "Y*M distributed count"); counterInit(7, "Tranpose count"); counterInit(8, "Transpose bytes"); counterInit(9, "matrix*matrix flop count"); counterInit(10, "matrix*matrix count"); counterInit(11, "diagonalization count"); counterInit(12, "I count"); counterInit(13, "Idag count"); counterInit(14, "J count"); counterInit(15, "Jdag count"); counterInit(16, "FFT3D count"); counterInit(17, "diaginner MPI_Allreduce count"); counterInit(18, "diaginner MPI_Allreduce bytes"); counterInit(19, "diagouterI MPI_Allreduce count"); counterInit(20, "diagouterI MPI_Allreduce bytes"); counterInit(21, "other MPI_Allreduce count"); counterInit(22, "other MPI_Allreduce bytes"); // My additions to the operator counts. counterInit(23, "L count"); counterInit(24, "O count"); #ifdef WAVELETS counterInit(25, "Get/Put count"); #endif // WAVELETS return 24; } void counterInitAll(void) { num_counters = 0; for (int i=0; i < NUM_COUNTERS; i++) counterState[i] = 0.0; } void counterInit(int counter, char* title) { counterState[counter] = 0.0; strcpy(counterTitle[counter], title); if ((counter+1) > num_counters) { num_counters = counter + 1; } } void counterIncr(int counter) { counterState[counter] += 1.0; } void counterIncr(int counter, double amount) { counterState[counter] += amount; } double counterRead(int counter) { return counterState[counter]; } char * counterGetTitle(int counter) { return (counterTitle[counter]); } int counterGetTotal(void) { return num_counters; } #endif // DFT_PROFILING