/* This file is part of the OpenLB library
*
* Copyright (C) 2011 Lukas Baron, Mathias J. Krause
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* This program 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.
*
* This program 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 this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TIMER_HH
#define TIMER_HH
#include "timer.h"
#include "communication/mpiManager.h"
namespace olb {
namespace util {
template
Timer::Timer(int maxTimeSteps, size_t numFluidCells)
: clout(std::cout,"Timer"),
deltaTS(0), curTS(0), maxTS(maxTimeSteps),
numFC(numFluidCells), rtRemMs(1) // avoids some stupid numbers in first call of printStep() (not for T=double)
{
tp = nullptr;
}
template
T Timer::timevalDiffTimeMs(timeval end, timeval start)
{
T msDiff;
msDiff = 1000*(end.tv_sec - start.tv_sec)
+(end.tv_usec-start.tv_usec)/1000;
return std::max(msDiff, 1.0);
}
template
T Timer::getMLUPs()
{
T mlups = (numFC * deltaTS) / (timevalDiffTimeMs(msTimeCur, msTimeLast)*1000);
return mlups;
}
template
T Timer::getMLUPps()
{
T mlupps = getMLUPs()/singleton::mpi().getSize();
return mlupps;
}
template
T Timer::getTotalMLUPs()
{
T tmlups = ((T)numFC * curTS) / (timevalDiffTimeMs(msTimeEnd, msTimeStart)*1000);
return tmlups;
}
template
T Timer::getTotalMLUPps()
{
T tmlupps = getTotalMLUPs()/singleton::mpi().getSize();
return tmlupps;
}
template
void Timer::start()
{
sTimeStart = time(tp); // time in s
gettimeofday(&msTimeStart, nullptr); // time in ms
gettimeofday(&msTimeCur, nullptr); // time in ms, here only necessary for MLUP-calculations
cpuTimeStart = clock(); //cpu-time
}
template
void Timer::update(int currentTimeStep) // Is int sufficient? Is it possible/desirable to have non-integer time steps?
{
cpuTimeCur = clock(); // CPU-time
sTimeCur = time(tp); // time in s
msTimeLast = msTimeCur;
gettimeofday(&msTimeCur, nullptr); // time in ms
// calculate and update missing time-values
deltaTS = currentTimeStep - curTS; // this makes multiple calls
curTS = currentTimeStep; // of update() critical
rtPas = difftime(sTimeCur,sTimeStart); // here calculation is based on s-time
rtTot = rtPas*maxTS/std::max(curTS, 1);
rtRem = rtTot-rtPas;
rtPasMs = timevalDiffTimeMs(msTimeCur, msTimeStart); // here with ms-time as timeval-value
rtTotMs = rtPasMs*maxTS/std::max(curTS, 1);
rtRemMs = rtTotMs-rtPasMs;
ctPas = (cpuTimeCur-cpuTimeStart)/CLOCKS_PER_SEC; // and here the same for CPU-time
ctTot = ctPas*maxTS/std::max(curTS, 1);
ctRem = ctTot-ctPas;
}
template
void Timer::stop()
{
cpuTimeEnd = clock(); // cpu-time
sTimeEnd = time(tp); // time in s
gettimeofday(&msTimeEnd, nullptr); // time in ms
}
template
double Timer::getTotalCpuTime()
{
return (cpuTimeEnd-cpuTimeStart)/CLOCKS_PER_SEC;
}
template
T Timer::getTotalRealTime()
{
return difftime(sTimeEnd,sTimeStart);
}
template
T Timer::getTotalRealTimeMs()
{
return timevalDiffTimeMs(msTimeEnd, msTimeStart);
}
template
void Timer::print(int currentTimeStep, int printMode)
{
if (currentTimeStep!=curTS) {
update(currentTimeStep);
}
printStep(printMode);
}
template
void Timer::printStep(int printMode)
{
switch (printMode) {
case 0: //single-line layout, usable for data extraction as csv
clout
<< "step=" << curTS << "; "
// << "stepMax=" << maxTS << "; "
<< "percent=" << 100.0*curTS/maxTS << "; "
<< "passedTime=" << (double)rtPasMs/1000 << "; "
// << "totalTime=" << (double)rtTotMs/1000 << "; "
<< "remTime=" << rtRemMs/1000 << "; "
<< "MLUPs=" << getMLUPs()
<< std::endl;
break;
case 1: //single-line layout (not conform with output-rules)
clout
<< "latticeTS: "
<< curTS << "/" << maxTS << " (" << 100*curTS/maxTS << "%); "
<< "pas/totTime: "
<< std::setprecision(2) << std::fixed << (double)rtPasMs/1000 << "/"
<< std::setprecision(1) << std::fixed << (double)rtTotMs/1000 << "s; "
<< "remTime: "
<< std::setw(2) << (int)((double)rtRemMs/1000)/60 << "m " << std::setfill('0') << std::setw(4) << (double)((int)((double)rtRemMs/100)%600)/10 << "s; "
<< std::setfill(' ')
<< "MLUPs: " << getMLUPs()
<< std::endl;
break;
case 2: //pretty double line layout in colums, but non-conform
clout
<< std::setw(21) << std::left << "Lattice-Timesteps"
<< std::setw(17) << std::left << "| CPU time/estim"
<< std::setw(18) << std::left << "| REAL time/estim"
<< std::setw(6) << std::left << "| ETA"
<< std::setw(6) << std::left << "| MLUPs"
<< std::endl << std::right
<< std::setw(6) << std::setprecision(2) << std::fixed << curTS << "/" << std::setw(6) << maxTS << " (" << std::setw(3) << 100*curTS/maxTS << "%) |"
<< std::setw(7) << ctPas << "/" << std::setw(7) << ctTot << " |"
<< std::setw(8) << (double)rtPasMs/1000 << "/" << std::setw(7) << (double)rtTotMs/1000 << " |"
<< std::setw(4) << (int)rtRemMs/1000+1 << " |"
<< std::setw(6) << getMLUPs()
<< std::endl;
break;
case 3: //performance output only
clout
<< "step " << curTS << "; "
<< "MLUPs=" << std::setw(8) << getMLUPs() << ", MLUPps=" << std::setw(8) << getMLUPps() << std::endl;
break;
default:
clout << "Error in function printStep in class_timer.h: printMode="<
void Timer::printSummary()
{
clout << std::endl;
clout << "----------------Summary:Timer----------------" << std::endl;
clout << "measured time (rt) : " << (int)getTotalRealTimeMs()/1000 << "." << (int)getTotalRealTimeMs()-(int)getTotalRealTimeMs()/1000*1000 << "s" << std::endl;
clout << "measured time (cpu): " << std::setprecision(3) << std::fixed << getTotalCpuTime() << "s" << std::endl;
clout << "average MLUPs : " << getTotalMLUPs() << std::endl;
clout << "average MLUPps: " << getTotalMLUPps() << std::endl;
clout << "---------------------------------------------" << std::endl;
}
template
void Timer::printShortSummary()
{
clout << "realTime=" << (int)getTotalRealTimeMs()/1000 << "." << (int)getTotalRealTimeMs()-(int)getTotalRealTimeMs()/1000*1000
<< "; cpuTime=" << std::setprecision(3) << std::fixed << getTotalCpuTime() << std::endl;
}
// Factory function /////////////////////////////////
template
Timer* createTimer(XMLreader& param, const UnitConverter& converter, size_t numLatticePoints)
{
OstreamManager clout(std::cout,"createTimer");
// initialize parameters with some default values
T physMaxT = T();
T physStartT = T();
// fetch xml Data and error handling
if ( ! param["Application"]["PhysParameters"]["PhysMaxTime"].read(physMaxT) ) {
if ( ! param["Application"]["PhysParam"]["MaxTime"].read(physStartT) ) {
clout << "PhysMaxTime not found" << std::endl;
}
else
{
clout << "Application::PhysParam::MaxTime needs to be renamed to Application::PhysParameters::PhysMaxTime" << std::endl;
}
}
// if ( ! param["Application"]["PhysParam"]["MaxStartTime"].read(physStartT) ) {
// clout << "PhysStartTime not found" << std::endl;
// }
// variable processing according to the constructor
int maxT = converter.getLatticeTime(physMaxT) + converter.getLatticeTime(physStartT);
//return some default values that produce reasonable output (e.g.
// zero); in best case there should be no output at all (TODO)
return new Timer(maxT, numLatticePoints);
}
} // namespace util
} // namespace olb
#endif