|
@@ -1,6 +1,6 @@
|
|
|
/*
|
|
|
* StarPU
|
|
|
- * Copyright (C) INRIA 2008-2009 (see AUTHORS file)
|
|
|
+ * Copyright (C) INRIA 2008-2010 (see AUTHORS file)
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
@@ -16,51 +16,83 @@
|
|
|
|
|
|
#include "timing.h"
|
|
|
|
|
|
-static double reference_start_time;
|
|
|
-
|
|
|
#ifdef HAVE_CLOCK_GETTIME
|
|
|
-
|
|
|
-#define TICK_DIFF(t1, t2) ((long long)((t2).ts.tv_sec*1e9 + (t2).ts.tv_nsec) + \
|
|
|
- - (long long)((t1).ts.tv_sec*1e9) + (long long)(t1).ts.tv_nsec)
|
|
|
-#define TIMING_DELAY(t1, t2) _starpu_tick2usec(TICK_DIFF((t1), (t2)))
|
|
|
-
|
|
|
-void _starpu_timing_init(void)
|
|
|
-{
|
|
|
- reference_start_time = _starpu_timing_now();
|
|
|
+#include <time.h>
|
|
|
+#ifndef _POSIX_C_SOURCE
|
|
|
+/* for clock_gettime */
|
|
|
+#define _POSIX_C_SOURCE 199309L
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef __linux__
|
|
|
+#ifndef CLOCK_MONOTONIC_RAW
|
|
|
+#define CLOCK_MONOTONIC_RAW 4
|
|
|
+#endif
|
|
|
+#endif
|
|
|
+
|
|
|
+static struct timespec reference_start_time_ts;
|
|
|
+
|
|
|
+/* Modern CPUs' clocks are usually not synchronized so we use a monotonic clock
|
|
|
+ * to have consistent timing measurements. The CLOCK_MONOTONIC_RAW clock is not
|
|
|
+ * subject to NTP adjustments, but is not available on all systems (in that
|
|
|
+ * case we use the CLOCK_MONOTONIC clock instead). */
|
|
|
+void __starpu_clock_gettime(struct timespec *ts) {
|
|
|
+#ifdef CLOCK_MONOTONIC_RAW
|
|
|
+ static int raw_supported = 0;
|
|
|
+ switch (raw_supported) {
|
|
|
+ case -1:
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ clock_gettime(CLOCK_MONOTONIC_RAW, ts);
|
|
|
+ return;
|
|
|
+ case 0:
|
|
|
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, ts)) {
|
|
|
+ raw_supported = -1;
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ raw_supported = 1;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ clock_gettime(CLOCK_MONOTONIC, ts);
|
|
|
}
|
|
|
|
|
|
-inline double _starpu_tick2usec(long long t)
|
|
|
+void _starpu_timing_init(void)
|
|
|
{
|
|
|
- return (double)(t)/1000;
|
|
|
+ __starpu_clock_gettime(&reference_start_time_ts);
|
|
|
}
|
|
|
|
|
|
-inline double _starpu_timing_delay(starpu_tick_t *t1, starpu_tick_t *t2)
|
|
|
+void starpu_clock_gettime(struct timespec *ts)
|
|
|
{
|
|
|
- double d1, d2;
|
|
|
+ struct timespec absolute_ts;
|
|
|
|
|
|
- d1 = _starpu_tick2usec((t1->ts.tv_sec*1e9) + t1->ts.tv_nsec);
|
|
|
- d2 = _starpu_tick2usec((t2->ts.tv_sec*1e9) + t2->ts.tv_nsec);
|
|
|
+ /* Read the current time */
|
|
|
+ __starpu_clock_gettime(&absolute_ts);
|
|
|
|
|
|
- return (d2 - d1);;
|
|
|
+ /* Compute the relative time since initialization */
|
|
|
+ _starpu_timespec_sub(&absolute_ts, &reference_start_time_ts, ts);
|
|
|
}
|
|
|
|
|
|
-/* returns the current time in us */
|
|
|
-inline double _starpu_timing_now(void)
|
|
|
-{
|
|
|
- starpu_tick_t tick_now;
|
|
|
- STARPU_GET_TICK(tick_now);
|
|
|
+#else // !HAVE_CLOCK_GETTIME
|
|
|
|
|
|
- double absolute_now = _starpu_tick2usec(((tick_now).ts.tv_sec*1e9) + (tick_now).ts.tv_nsec);
|
|
|
-
|
|
|
- return (absolute_now - reference_start_time);
|
|
|
-}
|
|
|
+#if defined(__i386__) || defined(__pentium__) || defined(__pentiumpro__) || defined(__i586__) || defined(__i686__) || defined(__k6__) || defined(__k7__) || defined(__x86_64__)
|
|
|
+typedef union starpu_u_tick
|
|
|
+{
|
|
|
+ uint64_t tick;
|
|
|
|
|
|
-#else // HAVE_CLOCK_GETTIME
|
|
|
+ struct
|
|
|
+ {
|
|
|
+ uint32_t low;
|
|
|
+ uint32_t high;
|
|
|
+ }
|
|
|
+ sub;
|
|
|
+} starpu_tick_t;
|
|
|
|
|
|
+#define STARPU_GET_TICK(t) __asm__ volatile("rdtsc" : "=a" ((t).sub.low), "=d" ((t).sub.high))
|
|
|
#define TICK_RAW_DIFF(t1, t2) ((t2).tick - (t1).tick)
|
|
|
#define TICK_DIFF(t1, t2) (TICK_RAW_DIFF(t1, t2) - residual)
|
|
|
-#define TIMING_DELAY(t1, t2) _starpu_tick2usec(TICK_DIFF(t1, t2))
|
|
|
|
|
|
+static starpu_tick_t reference_start_tick;
|
|
|
static double scale = 0.0;
|
|
|
static unsigned long long residual = 0;
|
|
|
|
|
@@ -95,30 +127,64 @@ void _starpu_timing_init(void)
|
|
|
(double)(TICK_DIFF(t1, t2));
|
|
|
}
|
|
|
|
|
|
- reference_start_time = _starpu_timing_now();
|
|
|
+ STARPU_GET_TICK(reference_start_tick);
|
|
|
|
|
|
inited = 1;
|
|
|
}
|
|
|
|
|
|
-inline double _starpu_tick2usec(long long t)
|
|
|
+void starpu_clock_gettime(struct timespec *ts)
|
|
|
{
|
|
|
- return (double)(t)*scale;
|
|
|
+ starpu_tick_t tick_now;
|
|
|
+
|
|
|
+ STARPU_GET_TICK(tick_now);
|
|
|
+
|
|
|
+ uint64_t elapsed_ticks = TICK_DIFF(reference_start_tick, tick_now);
|
|
|
+
|
|
|
+ /* We convert this number into nano-seconds so that we can fill the
|
|
|
+ * timespec structure. */
|
|
|
+ uint64_t elapsed_ns = (uint64_t)(((double)elapsed_ticks)*(scale*1000.0));
|
|
|
+
|
|
|
+ long tv_nsec = (elapsed_ns % 1000000000);
|
|
|
+ time_t tv_sec = (elapsed_ns / 1000000000);
|
|
|
+
|
|
|
+ ts->tv_sec = tv_sec;
|
|
|
+ ts->tv_nsec = tv_nsec;
|
|
|
}
|
|
|
|
|
|
-inline double _starpu_timing_delay(starpu_tick_t *t1, starpu_tick_t *t2)
|
|
|
+#else // !HAVE_CLOCK_GETTIME & no rdtsc
|
|
|
+#warning StarPU could not find a timer, clock will always return 0
|
|
|
+void _starpu_timing_init(void)
|
|
|
{
|
|
|
- return TIMING_DELAY(*t1, *t2);
|
|
|
}
|
|
|
|
|
|
-inline double _starpu_timing_now(void)
|
|
|
+void starpu_clock_gettime(struct timespec *ts)
|
|
|
{
|
|
|
- starpu_tick_t tick_now;
|
|
|
- STARPU_GET_TICK(tick_now);
|
|
|
+ timerclear(ts);
|
|
|
+}
|
|
|
+#endif
|
|
|
+#endif // HAVE_CLOCK_GETTIME
|
|
|
|
|
|
- double absolute_now = _starpu_tick2usec(tick_now.tick);
|
|
|
+/* Returns the time elapsed between start and end in microseconds */
|
|
|
+double _starpu_timing_timespec_delay_us(struct timespec *start, struct timespec *end)
|
|
|
+{
|
|
|
+ struct timespec diff;
|
|
|
+
|
|
|
+ _starpu_timespec_sub(end, start, &diff);
|
|
|
|
|
|
- return (absolute_now - reference_start_time);
|
|
|
+ double us = (diff.tv_sec*1e6) + (diff.tv_nsec*1e-3);
|
|
|
|
|
|
+ return us;
|
|
|
}
|
|
|
|
|
|
-#endif // HAVE_CLOCK_GETTIME
|
|
|
+double _starpu_timing_timespec_to_us(struct timespec *ts)
|
|
|
+{
|
|
|
+ return (ts->tv_sec*1e6) + (ts->tv_nsec*1e-3);
|
|
|
+}
|
|
|
+
|
|
|
+double _starpu_timing_now(void)
|
|
|
+{
|
|
|
+ struct timespec now;
|
|
|
+ starpu_clock_gettime(&now);
|
|
|
+
|
|
|
+ return _starpu_timing_timespec_to_us(&now);
|
|
|
+}
|