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