[mlpack-git] master: Changes to solve issue #498: Replacing timer implementation (d91cf4a)
gitdub at mlpack.org
gitdub at mlpack.org
Mon Mar 14 01:04:47 EDT 2016
Repository : https://github.com/mlpack/mlpack
On branch : master
Link : https://github.com/mlpack/mlpack/compare/f77416e9ab5bb5d327805f7cb61bf206431ddfed...c0886a18f63c9335a0c39dcc34c27b8925dcb91b
>---------------------------------------------------------------
commit d91cf4a966faead743c61c1552e3f99289437892
Author: na1taneja2821 <namantaneja821 at gmail.com>
Date: Mon Mar 14 10:34:47 2016 +0530
Changes to solve issue #498: Replacing timer implementation
>---------------------------------------------------------------
d91cf4a966faead743c61c1552e3f99289437892
src/mlpack/core/util/cli.cpp | 4 +-
src/mlpack/core/util/timers.cpp | 169 +++++++---------------------------------
src/mlpack/core/util/timers.hpp | 57 ++++----------
src/mlpack/tests/cli_test.cpp | 8 +-
4 files changed, 48 insertions(+), 190 deletions(-)
diff --git a/src/mlpack/core/util/cli.cpp b/src/mlpack/core/util/cli.cpp
index 451428b..0eaf543 100644
--- a/src/mlpack/core/util/cli.cpp
+++ b/src/mlpack/core/util/cli.cpp
@@ -55,7 +55,7 @@ CLI::CLI(const CLI& other) : desc(other.desc),
CLI::~CLI()
{
// Terminate the program timers.
- std::map<std::string, timeval>::iterator it;
+ std::map<std::string, std::chrono::microseconds>::iterator it;
for (it = timer.GetAllTimers().begin(); it != timer.GetAllTimers().end();
++it)
{
@@ -72,7 +72,7 @@ CLI::~CLI()
Print();
Log::Info << "Program timers:" << std::endl;
- std::map<std::string, timeval>::iterator it;
+ std::map<std::string, std::chrono::microseconds>::iterator it;
for (it = timer.GetAllTimers().begin(); it != timer.GetAllTimers().end();
++it)
{
diff --git a/src/mlpack/core/util/timers.cpp b/src/mlpack/core/util/timers.cpp
index 4323cb5..eaf6255 100644
--- a/src/mlpack/core/util/timers.cpp
+++ b/src/mlpack/core/util/timers.cpp
@@ -14,19 +14,11 @@
using namespace mlpack;
-// On Windows machines, we need to define timersub.
-#ifdef _WIN32
-inline void timersub(const timeval* tvp, const timeval* uvp, timeval* vvp)
+inline std::chrono::microseconds getTimeDuration(const std::chrono::high_resolution_clock::time_point start,
+ const std::chrono::high_resolution_clock::time_point end)
{
- vvp->tv_sec = tvp->tv_sec - uvp->tv_sec;
- vvp->tv_usec = tvp->tv_usec - uvp->tv_usec;
- if (vvp->tv_usec < 0)
- {
- --vvp->tv_sec;
- vvp->tv_usec += 1000000;
- }
+ return std::chrono::duration_cast<std::chrono::microseconds>(end - start);
}
-#endif
/**
* Start the given timer.
@@ -47,17 +39,17 @@ void Timer::Stop(const std::string& name)
/**
* Get the given timer.
*/
-timeval Timer::Get(const std::string& name)
+std::chrono::microseconds Timer::Get(const std::string& name)
{
return CLI::GetSingleton().timer.GetTimer(name);
}
-std::map<std::string, timeval>& Timers::GetAllTimers()
+std::map<std::string, std::chrono::microseconds>& Timers::GetAllTimers()
{
return timers;
}
-timeval Timers::GetTimer(const std::string& timerName)
+std::chrono::microseconds Timers::GetTimer(const std::string& timerName)
{
return timers[timerName];
}
@@ -69,15 +61,18 @@ bool Timers::GetState(std::string timerName)
void Timers::PrintTimer(const std::string& timerName)
{
- timeval& t = timers[timerName];
- Log::Info << t.tv_sec << "." << std::setw(6) << std::setfill('0')
- << t.tv_usec << "s";
+ long long int totalDuration = timers[timerName].count();
+ // Converting microseconds to seconds
+ long long int totalDurationSec = totalDuration / 1e6;
+ long long int totalDurationMicroSec = totalDuration % 1000000;
+ Log::Info << totalDurationSec << "." << std::setw(6) << std::setfill('0')
+ << totalDurationMicroSec << "s";
// Also output convenient day/hr/min/sec.
- int days = t.tv_sec / 86400; // Integer division rounds down.
- int hours = (t.tv_sec % 86400) / 3600;
- int minutes = (t.tv_sec % 3600) / 60;
- int seconds = (t.tv_sec % 60);
+ int days = totalDurationSec / 86400; // Integer division rounds down.
+ int hours = (totalDurationSec % 86400) / 3600;
+ int minutes = (totalDurationSec % 3600) / 60;
+ int seconds = (totalDurationSec % 60);
// No output if it didn't even take a minute.
if (!(days == 0 && hours == 0 && minutes == 0))
{
@@ -111,7 +106,7 @@ void Timers::PrintTimer(const std::string& timerName)
{
if (output)
Log::Info << ", ";
- Log::Info << seconds << "." << std::setw(1) << (t.tv_usec / 100000) <<
+ Log::Info << seconds << "." << std::setw(1) << (totalDurationMicroSec / 100000) <<
"secs";
output = true;
}
@@ -122,90 +117,9 @@ void Timers::PrintTimer(const std::string& timerName)
Log::Info << std::endl;
}
-void Timers::GetTime(timeval* tv)
+std::chrono::high_resolution_clock::time_point Timers::GetTime()
{
-#if defined(__MACH__) && defined(__APPLE__)
-
- static mach_timebase_info_data_t info;
-
- // If this is the first time we've run, get the timebase.
- // We can use denom == 0 to indicate that sTimebaseInfo is
- // uninitialised.
- if (info.denom == 0) {
- (void) mach_timebase_info(&info);
- }
-
- // Hope that the multiplication doesn't overflow.
- uint64_t nsecs = mach_absolute_time() * info.numer / info.denom;
- tv->tv_sec = nsecs / 1e9;
- tv->tv_usec = (nsecs / 1e3) - (tv->tv_sec * 1e6);
-
-#elif defined(_POSIX_VERSION)
-#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
-
- // Get the right clock_id.
-#if defined(CLOCK_MONOTONIC_PRECISE)
- static const clockid_t id = CLOCK_MONOTONIC_PRECISE;
-#elif defined(CLOCK_MONOTONIC_RAW)
- static const clockid_t id = CLOCK_MONOTONIC_RAW;
-#elif defined(CLOCK_MONOTONIC)
- static const clockid_t id = CLOCK_MONOTONIC;
-#elif defined(CLOCK_REALTIME)
- static const clockid_t id = CLOCK_REALTIME;
-#else
- static const clockid_t id = ((clockid_t) - 1);
-#endif // CLOCK
-
- struct timespec ts;
-
- // Returns the current value tp for the specified clock_id.
- if (clock_gettime(id, &ts) != -1 && id != ((clockid_t) - 1))
- {
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / 1e3;
- }
-
- // Fallback for the clock_gettime function.
- gettimeofday(tv, NULL);
-
-#endif // _POSIX_TIMERS
-#elif defined(_WIN32)
-
- static double frequency = 0.0;
- static LARGE_INTEGER offset;
-
- // If this is the first time we've run, get the frequency.
- // We use frequency == 0.0 to indicate that
- // QueryPerformanceFrequency is uninitialised.
- if (frequency == 0.0)
- {
- LARGE_INTEGER pF;
- if (!QueryPerformanceFrequency(&pF))
- {
- // Fallback for the QueryPerformanceCounter function.
- FileTimeToTimeVal(tv);
- }
- else
- {
- QueryPerformanceCounter(&offset);
- frequency = (double)pF.QuadPart / 1000000.0;
- }
- }
-
- if (frequency != 0.0)
- {
- LARGE_INTEGER pC;
- // Get the current performance-counter value.
- QueryPerformanceCounter(&pC);
-
- pC.QuadPart -= offset.QuadPart;
- double microseconds = (double)pC.QuadPart / frequency;
- pC.QuadPart = microseconds;
- tv->tv_sec = (long)pC.QuadPart / 1000000;
- tv->tv_usec = (long)(pC.QuadPart % 1000000);
- }
-
-#endif
+ return std::chrono::high_resolution_clock::now();
}
void Timers::StartTimer(const std::string& timerName)
@@ -220,44 +134,16 @@ void Timers::StartTimer(const std::string& timerName)
timerState[timerName] = true;
- timeval tmp;
- tmp.tv_sec = 0;
- tmp.tv_usec = 0;
+ std::chrono::high_resolution_clock::time_point currTime = GetTime();
- GetTime(&tmp);
-
- // Check to see if the timer already exists. If it does, we'll subtract the
- // old value.
- if (timers.count(timerName) == 1)
+ // If the timer is added first time
+ if(timers.count(timerName) == 0)
{
- timeval tmpDelta;
-
- timersub(&tmp, &timers[timerName], &tmpDelta);
-
- tmp = tmpDelta;
+ timers[timerName] = (std::chrono::microseconds)0;
}
- timers[timerName] = tmp;
-}
-
-#ifdef _WIN32
-void Timers::FileTimeToTimeVal(timeval* tv)
-{
- FILETIME ftime;
- uint64_t ptime = 0;
- // Acquire the file time.
- GetSystemTimeAsFileTime(&ftime);
- // Now convert FILETIME to timeval.
- ptime |= ftime.dwHighDateTime;
- ptime = ptime << 32;
- ptime |= ftime.dwLowDateTime;
- ptime /= 10;
- ptime -= DELTA_EPOCH_IN_MICROSECS;
-
- tv->tv_sec = (long) (ptime / 1000000UL);
- tv->tv_usec = (long) (ptime % 1000000UL);
+ timerStartTime[timerName] = currTime;
}
-#endif // _WIN32
void Timers::StopTimer(const std::string& timerName)
{
@@ -271,11 +157,8 @@ void Timers::StopTimer(const std::string& timerName)
timerState[timerName] = false;
- timeval delta, b, a = timers[timerName];
-
- GetTime(&b);
+ std::chrono::high_resolution_clock::time_point currTime = GetTime();
// Calculate the delta time.
- timersub(&b, &a, &delta);
- timers[timerName] = delta;
+ timers[timerName] += getTimeDuration(timerStartTime[timerName], currTime);
}
diff --git a/src/mlpack/core/util/timers.hpp b/src/mlpack/core/util/timers.hpp
index fb55e73..2ec4f82 100644
--- a/src/mlpack/core/util/timers.hpp
+++ b/src/mlpack/core/util/timers.hpp
@@ -10,46 +10,17 @@
#include <map>
#include <string>
+#include <chrono> // chrono library for cross platform timer calculation
-#if defined(__unix__) || defined(__unix)
- #include <time.h> // clock_gettime()
- #include <sys/time.h> // timeval, gettimeofday()
- #include <unistd.h> // flags like _POSIX_VERSION
-#elif defined(__MACH__) && defined(__APPLE__)
- #include <mach/mach_time.h> // mach_timebase_info,
- // mach_absolute_time()
-
- // TEMPORARY
- #include <time.h> // clock_gettime()
- #include <sys/time.h> // timeval, gettimeofday()
- #include <unistd.h> // flags like _POSIX_VERSION
-#elif defined(_WIN32)
- #ifndef NOMINMAX
- #define NOMINMAX // Don't define min and max macros.
- #endif
- #include <windows.h> // GetSystemTimeAsFileTime(),
- // QueryPerformanceFrequency(),
- // QueryPerformanceCounter()
- #include <winsock.h> // timeval on windows
- #undef NOMINMAX
-
- // uint64_t isn't defined on every windows.
+#if defined(_WIN32)
+ // uint64_t isn't defined on every windows.
#if !defined(HAVE_UINT64_T)
- #if SIZEOF_UNSIGNED_LONG == 8
- typedef unsigned long uint64_t;
- #else
- typedef unsigned long long uint64_t;
- #endif // SIZEOF_UNSIGNED_LONG
+ #if SIZEOF_UNSIGNED_LONG == 8
+ typedef unsigned long uint64_t;
+ #else
+ typedef unsigned long long uint64_t;
+ #endif // SIZEOF_UNSIGNED_LONG
#endif // HAVE_UINT64_T
-
- //gettimeofday has no equivalent will need to write extra code for that.
- #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
- #else
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
- #endif // _MSC_VER, _MSC_EXTENSIONS
-#else
- #error "unknown OS"
#endif
namespace mlpack {
@@ -90,7 +61,7 @@ class Timer
*
* @param name Name of timer to return value of.
*/
- static timeval Get(const std::string& name);
+ static std::chrono::microseconds Get(const std::string& name);
};
class Timers
@@ -102,14 +73,14 @@ class Timers
/**
* Returns a copy of all the timers used via this interface.
*/
- std::map<std::string, timeval>& GetAllTimers();
+ std::map<std::string, std::chrono::microseconds>& GetAllTimers();
/**
* Returns a copy of the timer specified.
*
* @param timerName The name of the timer in question.
*/
- timeval GetTimer(const std::string& timerName);
+ std::chrono::microseconds GetTimer(const std::string& timerName);
/**
* Prints the specified timer. If it took longer than a minute to complete
@@ -146,12 +117,14 @@ class Timers
private:
//! A map of all the timers that are being tracked.
- std::map<std::string, timeval> timers;
+ std::map<std::string, std::chrono::microseconds> timers;
//! A map that contains whether or not each timer is currently running.
std::map<std::string, bool> timerState;
+ //! A map for the starting values of the timers.
+ std::map<std::string, std::chrono::high_resolution_clock::time_point> timerStartTime;
void FileTimeToTimeVal(timeval* tv);
- void GetTime(timeval* tv);
+ std::chrono::high_resolution_clock::time_point GetTime();
};
} // namespace mlpack
diff --git a/src/mlpack/tests/cli_test.cpp b/src/mlpack/tests/cli_test.cpp
index 2a53457..32b2321 100644
--- a/src/mlpack/tests/cli_test.cpp
+++ b/src/mlpack/tests/cli_test.cpp
@@ -7,6 +7,8 @@
#include <iostream>
#include <sstream>
+#include <chrono>
+
#ifndef _WIN32
#include <sys/time.h>
#endif
@@ -240,7 +242,7 @@ BOOST_AUTO_TEST_CASE(MultiRunTimerTest)
Timer::Stop("test_timer");
- BOOST_REQUIRE_GE(Timer::Get("test_timer").tv_usec, 10000);
+ BOOST_REQUIRE_GE(Timer::Get("test_timer").count(), 10000);
// Restart it.
Timer::Start("test_timer");
@@ -253,7 +255,7 @@ BOOST_AUTO_TEST_CASE(MultiRunTimerTest)
Timer::Stop("test_timer");
- BOOST_REQUIRE_GE(Timer::Get("test_timer").tv_usec, 20000);
+ BOOST_REQUIRE_GE(Timer::Get("test_timer").count(), 20000);
// Just one more time, for good measure...
Timer::Start("test_timer");
@@ -266,7 +268,7 @@ BOOST_AUTO_TEST_CASE(MultiRunTimerTest)
Timer::Stop("test_timer");
- BOOST_REQUIRE_GE(Timer::Get("test_timer").tv_usec, 40000);
+ BOOST_REQUIRE_GE(Timer::Get("test_timer").count(), 40000);
}
BOOST_AUTO_TEST_CASE(TwiceStartTimerTest)
More information about the mlpack-git
mailing list