timing.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2008-2021 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include <starpu.h>
  17. #include <common/config.h>
  18. #include <starpu_util.h>
  19. #include <profiling/profiling.h>
  20. #include <common/timing.h>
  21. #include <math.h>
  22. #ifdef STARPU_SIMGRID
  23. #include <core/simgrid.h>
  24. #ifdef HAVE_SIMGRID_ENGINE_H
  25. #include <simgrid/engine.h>
  26. #endif
  27. #endif
  28. #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
  29. #include <windows.h>
  30. #endif
  31. #ifdef STARPU_SIMGRID
  32. void _starpu_timing_init(void)
  33. {
  34. }
  35. void _starpu_clock_gettime(struct timespec *ts)
  36. {
  37. #ifdef HAVE_SIMGRID_GET_CLOCK
  38. double now = simgrid_get_clock();
  39. #else
  40. double now = MSG_get_clock();
  41. #endif
  42. ts->tv_sec = floor(now);
  43. ts->tv_nsec = floor((now - ts->tv_sec) * 1000000000);
  44. }
  45. #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
  46. #include <time.h>
  47. #ifndef _POSIX_C_SOURCE
  48. /* for clock_gettime */
  49. #define _POSIX_C_SOURCE 199309L
  50. #endif
  51. #ifdef __linux__
  52. #ifndef CLOCK_MONOTONIC_RAW
  53. #define CLOCK_MONOTONIC_RAW 4
  54. #endif
  55. #endif
  56. static struct timespec _starpu_reference_start_time_ts;
  57. /* Modern CPUs' clocks are usually not synchronized so we use a monotonic clock
  58. * to have consistent timing measurements.
  59. */
  60. static void _starpu_clock_readtime(struct timespec *ts)
  61. {
  62. #if 0 /* def CLOCK_MONOTONIC_RAW */
  63. /* The CLOCK_MONOTONIC_RAW clock is not
  64. * subject to NTP adjustments, but is not available on all systems (in that
  65. * case we use the CLOCK_MONOTONIC clock instead). */
  66. /* In the distributed case, we *do* want NTP adjustments, to get
  67. * somehow-coherent traces, so this is disabled */
  68. static int raw_supported = 0;
  69. switch (raw_supported)
  70. {
  71. case -1:
  72. break;
  73. case 1:
  74. clock_gettime(CLOCK_MONOTONIC_RAW, ts);
  75. return;
  76. case 0:
  77. if (clock_gettime(CLOCK_MONOTONIC_RAW, ts))
  78. {
  79. raw_supported = -1;
  80. break;
  81. }
  82. else
  83. {
  84. raw_supported = 1;
  85. return;
  86. }
  87. }
  88. #endif
  89. clock_gettime(CLOCK_MONOTONIC, ts);
  90. }
  91. void _starpu_timing_init(void)
  92. {
  93. _starpu_clock_gettime(&_starpu_reference_start_time_ts);
  94. }
  95. void _starpu_clock_gettime(struct timespec *ts)
  96. {
  97. struct timespec absolute_ts;
  98. /* Read the current time */
  99. _starpu_clock_readtime(&absolute_ts);
  100. /* Compute the relative time since initialization */
  101. starpu_timespec_sub(&absolute_ts, &_starpu_reference_start_time_ts, ts);
  102. }
  103. #else // !HAVE_CLOCK_GETTIME
  104. #if defined(__i386__) || defined(__pentium__) || defined(__pentiumpro__) || defined(__i586__) || defined(__i686__) || defined(__k6__) || defined(__k7__) || defined(__x86_64__)
  105. union starpu_u_tick
  106. {
  107. uint64_t tick;
  108. struct
  109. {
  110. uint32_t low;
  111. uint32_t high;
  112. }
  113. sub;
  114. };
  115. #define STARPU_GET_TICK(t) __asm__ volatile("rdtsc" : "=a" ((t).sub.low), "=d" ((t).sub.high))
  116. #define STARPU_TICK_RAW_DIFF(t1, t2) ((t2).tick - (t1).tick)
  117. #define STARPU_TICK_DIFF(t1, t2) (STARPU_TICK_RAW_DIFF(t1, t2) - _starpu_residual)
  118. static union starpu_u_tick _starpu_reference_start_tick;
  119. static double _starpu_scale = 0.0;
  120. static unsigned long long _starpu_residual = 0;
  121. static int _starpu_inited = 0;
  122. #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
  123. static int mygettimeofday(struct timeval *tv, void *tz)
  124. {
  125. if (tv)
  126. {
  127. FILETIME ft;
  128. unsigned long long res;
  129. GetSystemTimeAsFileTime(&ft);
  130. /* 100-nanosecond intervals since January 1, 1601 */
  131. res = ft.dwHighDateTime;
  132. res <<= 32;
  133. res |= ft.dwLowDateTime;
  134. res /= 10;
  135. /* Now we have microseconds */
  136. res -= (((1970-1601)*365) + 89) * 24ULL * 3600ULL * 1000000ULL;
  137. /* Now we are based on epoch */
  138. tv->tv_sec = res / 1000000ULL;
  139. tv->tv_usec = res % 1000000ULL;
  140. }
  141. }
  142. #else
  143. #define mygettimeofday(tv,tz) gettimeofday(tv,tz)
  144. #endif
  145. void _starpu_timing_init(void)
  146. {
  147. static union starpu_u_tick t1, t2;
  148. int i;
  149. if (_starpu_inited) return;
  150. _starpu_residual = (unsigned long long)1 << 63;
  151. for(i = 0; i < 20; i++)
  152. {
  153. STARPU_GET_TICK(t1);
  154. STARPU_GET_TICK(t2);
  155. _starpu_residual = STARPU_MIN(_starpu_residual, STARPU_TICK_RAW_DIFF(t1, t2));
  156. }
  157. {
  158. struct timeval tv1,tv2;
  159. STARPU_GET_TICK(t1);
  160. mygettimeofday(&tv1,0);
  161. starpu_sleep(0.5);
  162. STARPU_GET_TICK(t2);
  163. mygettimeofday(&tv2,0);
  164. _starpu_scale = ((tv2.tv_sec*1e6 + tv2.tv_usec) -
  165. (tv1.tv_sec*1e6 + tv1.tv_usec)) /
  166. (double)(STARPU_TICK_DIFF(t1, t2));
  167. }
  168. STARPU_GET_TICK(_starpu_reference_start_tick);
  169. _starpu_inited = 1;
  170. }
  171. void _starpu_clock_gettime(struct timespec *ts)
  172. {
  173. union starpu_u_tick tick_now;
  174. STARPU_GET_TICK(tick_now);
  175. uint64_t elapsed_ticks = STARPU_TICK_DIFF(_starpu_reference_start_tick, tick_now);
  176. /* We convert this number into nano-seconds so that we can fill the
  177. * timespec structure. */
  178. uint64_t elapsed_ns = (uint64_t)(((double)elapsed_ticks)*(_starpu_scale*1000.0));
  179. long tv_nsec = (elapsed_ns % 1000000000);
  180. time_t tv_sec = (elapsed_ns / 1000000000);
  181. ts->tv_sec = tv_sec;
  182. ts->tv_nsec = tv_nsec;
  183. }
  184. #else // !HAVE_CLOCK_GETTIME & no rdtsc
  185. #warning StarPU could not find a timer, clock will always return 0
  186. void _starpu_timing_init(void)
  187. {
  188. }
  189. void _starpu_clock_gettime(struct timespec *ts)
  190. {
  191. ts->tv_sec = 0;
  192. ts->tv_nsec = 0;
  193. }
  194. #endif
  195. #endif // HAVE_CLOCK_GETTIME
  196. /* Returns the time elapsed between start and end in microseconds */
  197. double starpu_timing_timespec_delay_us(struct timespec *start, struct timespec *end)
  198. {
  199. struct timespec diff;
  200. starpu_timespec_sub(end, start, &diff);
  201. double us = (diff.tv_sec*1e6) + (diff.tv_nsec*1e-3);
  202. return us;
  203. }
  204. double starpu_timing_timespec_to_us(struct timespec *ts)
  205. {
  206. return (1000000.0*ts->tv_sec) + (0.001*ts->tv_nsec);
  207. }
  208. double starpu_timing_now(void)
  209. {
  210. #ifdef STARPU_SIMGRID
  211. # ifdef HAVE_SIMGRID_GET_CLOCK
  212. return simgrid_get_clock()*1000000;
  213. # else
  214. return MSG_get_clock()*1000000;
  215. # endif
  216. #else
  217. struct timespec now;
  218. _starpu_clock_gettime(&now);
  219. return starpu_timing_timespec_to_us(&now);
  220. #endif
  221. }