Simulations can take some time, and I'd like to know how long.
This is easy, right? Yes, it is. I've done it lots of times,
but every time I do, I curse myself for not using an old piece of code.
most likely, there is some standard, best way of doing this, but I haven't found it. Most recently, I did this: I made a simple object "EtaEstimator", that can be updated every (costly) time step and asked for an estimated time of "arrival" at any time. Here's the header:
most likely, there is some standard, best way of doing this, but I haven't found it. Most recently, I did this: I made a simple object "EtaEstimator", that can be updated every (costly) time step and asked for an estimated time of "arrival" at any time. Here's the header:
// eta.hpp
#include <ctime>
#include <cmath> // floor
#include <iostream>
class EtaEstimator {
public:
EtaEstimator(int );
// constuction starts the clock. Pass the number of steps
void update();
void print(std::ostream & ) const;
private:
double ct, etl; // cumulative time, estimated time left
int n, N; // steps taken, total amount of steps
clock_t tick; // time after update ((c) matlab)
// statics...
static const int secperday = 86400;
static const int secperhour = 3600;
static const int secperminute = 60;
};
std::ostream & operator<<(std::ostream & , const EtaEstimator & );
The members are straight forward too:
// eta.cpp
#include "eta.hpp"
EtaEstimator::EtaEstimator(int N) :
ct(0.0), etl(0.0), n(0), N(N) {
tick = clock();
}
void EtaEstimator::update() {
clock_t dt = clock() - tick;
tick += dt;
ct += (double(dt)/CLOCKS_PER_SEC); // prevent integer division
// CLOCKS_PER_SEC is defined in ctime
++n;
etl = (ct/n) * (N-n);
}
void EtaEstimator::print(std::ostream & os) const {
double etlprime = etl;
int days = floor(etlprime / secperday);
etlprime -= days * secperday;
int hours = floor(etlprime / secperhour);
etlprime -= hours * secperhour;
int minutes = floor(etlprime / secperminute);
etlprime -= minutes * secperminute;
int seconds = floor(etlprime);
os << (days > 0 ? std::to_string(days) + " " : "")
<< hours << ":"
<< (minutes < 10 ? "0" : "") << minutes << ":"
<< (seconds < 10 ? "0" : "") << seconds;
}
std::ostream & operator<<(std::ostream & os,
const EtaEstimator & eta) {
eta.print(os);
return os;
}
Typical usage of EtaEstimator would be the following:
#include <iostream>
#include "eta.hpp"
// about to do lots of work...
int N = 1000;
EtaEstimator eta(N);
for ( int n = 0; n < N; ++n ) {
// do something very expensive
eta.update()
std::cout << "\rETA: " << eta << std::flush;
}
// ...
PS: std::to_string is a C++11 feature, and can be ignored by using something like
if ( days > 0 ) os << days << " "; // else nothing at all
No comments:
Post a Comment