Feature #1983: Made CmiWallTimer monotonic in the common case 05/4705/14
authorVenkatN <vn7@illinois.edu>
Wed, 17 Oct 2018 16:38:23 +0000 (11:38 -0500)
committerRonak Buch <rabuch2@illinois.edu>
Wed, 13 Feb 2019 22:23:41 +0000 (16:23 -0600)
Reimplemented one of CmiWallTimer's commonly used code branches to use
the highest resolution steady clock from C++11 instead of gettimeofday.
The new implementation also stores the epoch in an integral time_point,
and uses the starting time of the program as the epoch to reduce the
internal floating-point error.

Change-Id: I4ad82339bda69b9a17ba408ed824d1dea36cdf74

src/conv-core/convcore.C
src/conv-core/hrctimer.C [new file with mode: 0644]
src/conv-core/hrctimer.h [new file with mode: 0644]
src/scripts/Make.depends
src/scripts/Makefile

index da3500c..efd2f66 100644 (file)
@@ -52,7 +52,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
+#include "hrctimer.h"
 #ifndef __STDC_FORMAT_MACROS
 # define __STDC_FORMAT_MACROS
 #endif
@@ -1035,7 +1035,6 @@ double CmiInitTime(void)
 
 void CmiTimerInit(char **argv)
 {
-  struct timeval tv;
   struct rusage ru;
   CpvInitialize(double, inittime_virtual);
 
@@ -1049,8 +1048,7 @@ void CmiTimerInit(char **argv)
 #endif
 if(CmiMyRank() == 0) /* initialize only  once */
   {
-    gettimeofday(&tv,0);
-    inittime_wallclock = (tv.tv_sec * 1.0) + (tv.tv_usec*0.000001);
+    inittime_wallclock = inithrc();
 #ifndef RUSAGE_WHO
     CpvAccess(inittime_virtual) = inittime_wallclock;
 #else
@@ -1088,18 +1086,9 @@ static double lastT = -1.0;
 
 double CmiWallTimer(void)
 {
-  struct timeval tv;
   double currenttime;
-
-  gettimeofday(&tv,0);
-  currenttime = (tv.tv_sec * 1.0) + (tv.tv_usec * 0.000001);
-#if CMK_ERROR_CHECKING
-  if (lastT > 0.0 && currenttime < lastT) {
-    currenttime = lastT;
-  }
-  lastT = currenttime;
-#endif
-  return _absoluteTime?currenttime:currenttime - inittime_wallclock;
+  currenttime = gethrctime();
+  return _absoluteTime?currenttime+inittime_wallclock:currenttime;
 }
 
 double CmiTimer(void)
@@ -1295,10 +1284,9 @@ static inline uint64_t PPC64_TimeBase(void)
   return result;
 }
 
-uint64_t __micro_timer (void) {
-  struct timeval tv;
-  gettimeofday( &tv, 0 );
-  return tv.tv_sec * 1000000ULL + tv.tv_usec;
+uint64_t __micro_timer (void)
+{
+  return gethrctime_micro();
 }
 
 void CmiTimerInit(char **argv)
diff --git a/src/conv-core/hrctimer.C b/src/conv-core/hrctimer.C
new file mode 100644 (file)
index 0000000..a172108
--- /dev/null
@@ -0,0 +1,27 @@
+#include <chrono>
+#include <type_traits>
+#include "hrctimer.h"
+#include <ratio>
+
+using clock_type=typename std::conditional<
+  std::chrono::high_resolution_clock::is_steady,
+  std::chrono::high_resolution_clock,
+  std::chrono::steady_clock>::type;
+static std::chrono::time_point<clock_type> epoch;
+
+double inithrc() { //defines our HRC epoch
+  epoch = clock_type::now();
+  return std::chrono::duration<double>(epoch.time_since_epoch()).count();
+}
+double gethrctime() {
+  auto timepoint = clock_type::now(); //gets HRC timepoint
+  auto time_since_epoch = timepoint-epoch; //gets the elapsed time since the start of HRC clock
+  double seconds = std::chrono::duration<double>(time_since_epoch).count(); //converts that time into seconds(double)
+  return seconds;
+}
+uint64_t gethrctime_micro() {
+  auto timepoint = clock_type::now(); //gets HRC timepoint
+  auto time_since_epoch = timepoint-epoch; //gets the elapsed time since the start of HRC clock
+  auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(time_since_epoch).count(); //converts that time into microseconds(integer)
+  return microseconds;
+}
diff --git a/src/conv-core/hrctimer.h b/src/conv-core/hrctimer.h
new file mode 100644 (file)
index 0000000..dae43ec
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef HRCTIMER_H
+#define HRCTIMER_H
+#include <inttypes.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+double inithrc();
+double gethrctime();
+uint64_t gethrctime_micro();
+#ifdef __cplusplus
+}
+#endif
+#endif
index 3faff4a..2e2617b 100644 (file)
@@ -2444,7 +2444,7 @@ convcore.o: convcore.C converse.h conv-header.h conv-config.h \
  conv-cpm.h conv-cpath.h conv-qd.h conv-random.h conv-lists.h \
  conv-trace.h persistent.h conv-rdma.h cmirdmautils.h debug-conv.h \
  sockRoutines.h conv-ccs.h ccs-server.h ckhashtable.h pup.h \
- memory-isomalloc.h quiescence.h cmibacktrace.c
+ memory-isomalloc.h quiescence.h cmibacktrace.c hrctimer.h
 
 converseProjections.o: converseProjections.C converse.h conv-header.h \
  conv-config.h conv-autoconfig.h conv-common.h conv-mach-common.h \
@@ -2627,6 +2627,8 @@ global-nop.o: global-nop.c converse.h conv-header.h conv-config.h \
 
 hilbert.o: hilbert.C hilbert.h
 
+hrctimer.o: hrctimer.C hrctimer.h
+
 init.o: init.C ckcheckpoint.h pup.h converse.h conv-header.h \
  conv-config.h conv-autoconfig.h conv-common.h conv-mach-common.h \
  conv-mach.h conv-mach-opt.h lrts-common.h cmiqueue.h pup_c.h lrtslock.h \
index f40c064..577b701 100644 (file)
@@ -502,7 +502,7 @@ CVLIBS=$(L)/libconv-core.a \
        $(L)/libccs-client.a $(L)/libconv-partition.a $(L)/libhwloc_embedded.a \
        $(L)/libconv-ldb.a
 
-LIBCONV_CORE=convcore.o conv-conds.o conv-taskQ.o queueing.o msgmgr.o \
+LIBCONV_CORE=convcore.o hrctimer.o conv-conds.o conv-taskQ.o queueing.o msgmgr.o \
        cpm.o cpthreads.o futures.o cldb.o random.o \
        debug-conv.o debug-conv++.o conv-ccs.o ccs-builtins.o middle-ccs.o \
        traceCore.o traceCoreCommon.o \