Scippy

SCIP

Solving Constraint Integer Programs

clock.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file clock.c
17  * @ingroup OTHER_CFILES
18  * @brief methods for clocks and timing issues
19  * @author Tobias Achterberg
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 #if defined(_WIN32) || defined(_WIN64)
26 #include <windows.h>
27 #else
28 #include <sys/times.h>
29 #include <sys/time.h>
30 #include <unistd.h>
31 #endif
32 #include <time.h>
33 
34 #include "scip/def.h"
35 #include "scip/pub_message.h"
36 #include "blockmemshell/memory.h"
37 #include "scip/set.h"
38 #include "scip/clock.h"
39 
40 #include "scip/struct_clock.h"
41 
42 /** converts CPU clock ticks into seconds */
43 static
45  clock_t cputime /**< clock ticks for CPU time */
46  )
47 {
48  clock_t clocks_per_second;
49 
50 #if defined(_WIN32) || defined(_WIN64)
51  clocks_per_second = 100;
52 #else
53 #ifndef CLK_TCK
54  clocks_per_second = sysconf(_SC_CLK_TCK);
55 #else
56  clocks_per_second = CLK_TCK;
57 #endif
58 #endif
59 
60  return (SCIP_Real)cputime / (SCIP_Real)clocks_per_second;
61 }
62 
63 /*lint -esym(*,timeval)*/
64 /*lint -esym(*,gettimeofday)*/
65 
66 /** converts wall clock time into seconds */
67 static
69  long sec, /**< seconds counter */
70  long usec /**< microseconds counter */
71  )
72 {
73  return (SCIP_Real)sec + 0.000001 * (SCIP_Real)usec;
74 }
75 
76 /** converts seconds into CPU clock ticks */
77 static
79  SCIP_Real sec, /**< seconds */
80  clock_t* cputime /**< pointer to store clock ticks for CPU time */
81  )
82 {
83  clock_t clocks_per_second;
84 
85  assert(cputime != NULL);
86 
87 #if defined(_WIN32) || defined(_WIN64)
88  clocks_per_second = 100;
89 #else
90 #ifndef CLK_TCK
91  clocks_per_second = sysconf(_SC_CLK_TCK);
92 #else
93  clocks_per_second = CLK_TCK;
94 #endif
95 #endif
96  *cputime = (clock_t)(sec * clocks_per_second);
97 }
98 
99 /** converts wall clock time into seconds */
100 static
102  SCIP_Real sec, /**< seconds */
103  long* wallsec, /**< pointer to store seconds counter */
104  long* wallusec /**< pointer to store microseconds counter */
105  )
106 {
107  assert(wallsec != NULL);
108  assert(wallusec != NULL);
109 
110  *wallsec = (long)sec;
111  *wallusec = (long)((sec - *wallsec) * 1000000.0);
112 }
113 
114 
115 /** sets the clock's type and converts the clock timer accordingly */
116 static
118  SCIP_CLOCK* clck, /**< clock timer */
119  SCIP_CLOCKTYPE newtype /**< new clock type */
120  )
121 {
122  assert(clck != NULL);
123  assert(newtype != SCIP_CLOCKTYPE_DEFAULT);
124 
125  if( clck->clocktype != newtype )
126  {
127  if( clck->clocktype == SCIP_CLOCKTYPE_DEFAULT )
128  {
129  assert(clck->nruns == 0);
130  clck->clocktype = newtype;
131  SCIPclockReset(clck);
132  SCIPdebugMessage("switched clock type to %d\n", newtype);
133  }
134  else
135  {
136  SCIP_Real sec;
137 
138  sec = SCIPclockGetTime(clck);
139  clck->clocktype = newtype;
140  SCIPclockSetTime(clck, sec);
141  SCIPdebugMessage("switched clock type to %d (%g seconds -> %g seconds)\n", newtype, sec, SCIPclockGetTime(clck));
142  }
143  }
144 }
145 
146 /** if the clock uses the default clock type and the default changed, converts the clock timer to the new type */
147 static
149  SCIP_CLOCK* clck, /**< clock timer */
150  SCIP_CLOCKTYPE defaultclocktype /**< default type of clock to use */
151  )
152 {
153  assert(clck != NULL);
154  assert(defaultclocktype != SCIP_CLOCKTYPE_DEFAULT);
155 
156  if( clck->usedefault && clck->clocktype != defaultclocktype )
157  clockSetType(clck, defaultclocktype);
158 }
159 
160 /** creates a clock and initializes it */
162  SCIP_CLOCK** clck, /**< pointer to clock timer */
163  SCIP_CLOCKTYPE clocktype /**< type of clock */
164  )
165 {
166  assert(clck != NULL);
167 
168  SCIP_ALLOC( BMSallocMemory(clck) );
169 
170  SCIPclockInit(*clck, clocktype);
171 
172  return SCIP_OKAY;
173 }
174 
175 /** frees a clock */
177  SCIP_CLOCK** clck /**< pointer to clock timer */
178  )
179 {
180  assert(clck != NULL);
181 
182  BMSfreeMemory(clck);
183 }
184 
185 /** initializes and resets a clock */
187  SCIP_CLOCK* clck, /**< clock timer */
188  SCIP_CLOCKTYPE clocktype /**< type of clock */
189  )
190 {
191  assert(clck != NULL);
192 
193  SCIPdebugMessage("initializing clock %p of type %d\n", (void*)clck, clocktype);
194  clck->enabled = TRUE;
195  clck->lasttime = 0.0;
196  SCIPclockSetType(clck, clocktype);
197 }
198 
199 /** completely stop the clock and reset the clock's counter to zero */
201  SCIP_CLOCK* clck /**< clock timer */
202  )
203 {
204  assert(clck != NULL);
205 
206  SCIPdebugMessage("resetting clock %p of type %d (usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
207  switch( clck->clocktype )
208  {
210  break;
211  case SCIP_CLOCKTYPE_CPU:
212  clck->data.cpuclock.user = 0;
213  break;
214  case SCIP_CLOCKTYPE_WALL:
215  clck->data.wallclock.sec = 0;
216  clck->data.wallclock.usec = 0;
217  break;
218  default:
219  SCIPerrorMessage("invalid clock type\n");
220  SCIPABORT();
221  }
222  clck->nruns = 0;
223 }
224 
225 /** enables the clock */
227  SCIP_CLOCK* clck /**< clock timer */
228  )
229 {
230  assert(clck != NULL);
231 
232  SCIPdebugMessage("enabling clock %p of type %d (usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
233 
234  clck->enabled = TRUE;
235 }
236 
237 /** disables and resets the clock */
239  SCIP_CLOCK* clck /**< clock timer */
240  )
241 {
242  assert(clck != NULL);
243 
244  SCIPdebugMessage("disabling clock %p of type %d (usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
245 
246  clck->enabled = FALSE;
247  SCIPclockReset(clck);
248 }
249 
250 /** enables or disables \p clck, depending on the value of the flag */
252  SCIP_CLOCK* clck, /**< the clock to be disabled/enabled */
253  SCIP_Bool enable /**< should the clock be enabled? */
254  )
255 {
256  assert(clck != NULL);
257 
258  if( enable )
259  SCIPclockEnable(clck);
260  else
261  SCIPclockDisable(clck);
262 }
263 
264 /** sets the type of the clock, overriding the default clock type, and resets the clock */
266  SCIP_CLOCK* clck, /**< clock timer */
267  SCIP_CLOCKTYPE clocktype /**< type of clock */
268  )
269 {
270  assert(clck != NULL);
271 
272  SCIPdebugMessage("setting type of clock %p (type %d, usedefault=%u) to %d\n",
273  (void*)clck, clck->clocktype, clck->usedefault, clocktype);
274 
275  clck->clocktype = clocktype;
276  clck->usedefault = (clocktype == SCIP_CLOCKTYPE_DEFAULT);
277  SCIPclockReset(clck);
278 }
279 
280 /** starts measurement of time in the given clock */
282  SCIP_CLOCK* clck, /**< clock timer */
283  SCIP_SET* set /**< global SCIP settings */
284  )
285 {
286  assert(clck != NULL);
287  assert(set != NULL);
288 
289  if( set->time_enabled && clck->enabled )
290  {
291  clockUpdateDefaultType(clck, set->time_clocktype);
292 
293  if( clck->nruns == 0 )
294  {
295 #if defined(_WIN32) || defined(_WIN64)
296  FILETIME creationtime;
297  FILETIME exittime;
298  FILETIME kerneltime;
299  FILETIME usertime;
300 #else
301  struct timeval tp; /*lint !e86*/
302  struct tms now;
303 #endif
304 
305  SCIPdebugMessage("starting clock %p (type %d, usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
306 
307  switch( clck->clocktype )
308  {
309  case SCIP_CLOCKTYPE_CPU:
310 #if defined(_WIN32) || defined(_WIN64)
311  GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
312  clck->data.cpuclock.user -= usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L;
313 #else
314  (void)times(&now);
315  clck->data.cpuclock.user -= now.tms_utime;
316 #endif
317  clck->lasttime = cputime2sec(clck->data.cpuclock.user);
318  break;
319 
320  case SCIP_CLOCKTYPE_WALL:
321 #if defined(_WIN32) || defined(_WIN64)
322  clck->data.wallclock.sec -= time(NULL);
323 #else
324  gettimeofday(&tp, NULL);
325  if( tp.tv_usec > clck->data.wallclock.usec ) /*lint !e115 !e40*/
326  {
327  clck->data.wallclock.sec -= (tp.tv_sec + 1); /*lint !e115 !e40*/
328  clck->data.wallclock.usec += (1000000 - tp.tv_usec); /*lint !e115 !e40*/
329  }
330  else
331  {
332  clck->data.wallclock.sec -= tp.tv_sec; /*lint !e115 !e40*/
333  clck->data.wallclock.usec -= tp.tv_usec; /*lint !e115 !e40*/
334  }
335 #endif
336  clck->lasttime = walltime2sec(clck->data.wallclock.sec, clck->data.wallclock.usec);
337  break;
338 
340  default:
341  SCIPerrorMessage("invalid clock type\n");
342  SCIPABORT();
343  }
344  }
345 
346  clck->nruns++;
347  }
348 }
349 
350 /** stops measurement of time in the given clock */
352  SCIP_CLOCK* clck, /**< clock timer */
353  SCIP_SET* set /**< global SCIP settings */
354  )
355 {
356  assert(clck != NULL);
357  assert(set != NULL);
358 
359  if( set->time_enabled && clck->enabled )
360  {
361  assert(clck->nruns >= 1);
362 
363  clck->nruns--;
364  if( clck->nruns == 0 )
365  {
366 #if defined(_WIN32) || defined(_WIN64)
367  FILETIME creationtime;
368  FILETIME exittime;
369  FILETIME kerneltime;
370  FILETIME usertime;
371 #else
372  struct timeval tp; /*lint !e86*/
373  struct tms now;
374 #endif
375 
376  SCIPdebugMessage("stopping clock %p (type %d, usedefault=%u)\n", (void*)clck, clck->clocktype, clck->usedefault);
377 
378  switch( clck->clocktype )
379  {
380  case SCIP_CLOCKTYPE_CPU:
381 #if defined(_WIN32) || defined(_WIN64)
382  GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
383  clck->data.cpuclock.user += usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L;
384 #else
385  (void)times(&now);
386  clck->data.cpuclock.user += now.tms_utime;
387 #endif
388  break;
389 
390  case SCIP_CLOCKTYPE_WALL:
391 #if defined(_WIN32) || defined(_WIN64)
392  clck->data.wallclock.sec += time(NULL);
393 #else
394  gettimeofday(&tp, NULL);
395  if( tp.tv_usec + clck->data.wallclock.usec > 1000000 ) /*lint !e115 !e40*/
396  {
397  clck->data.wallclock.sec += (tp.tv_sec + 1); /*lint !e115 !e40*/
398  clck->data.wallclock.usec -= (1000000 - tp.tv_usec); /*lint !e115 !e40*/
399  }
400  else
401  {
402  clck->data.wallclock.sec += tp.tv_sec; /*lint !e115 !e40*/
403  clck->data.wallclock.usec += tp.tv_usec; /*lint !e115 !e40*/
404  }
405 #endif
406  break;
407 
409  default:
410  SCIPerrorMessage("invalid clock type\n");
411  SCIPABORT();
412  }
413  }
414  }
415 }
416 
417 /** returns whether the clock is currently running */
419  SCIP_CLOCK* clck /**< clock timer */
420  )
421 {
422  assert(clck != NULL);
423 
424  return (clck->nruns > 0);
425 }
426 
427 
428 /** gets the used time of this clock in seconds */
430  SCIP_CLOCK* clck /**< clock timer */
431  )
432 {
433  SCIP_Real result;
434  assert(clck != NULL);
435  result = 0.0;
436 
437  SCIPdebugMessage("getting time of clock %p (type %d, usedefault=%u, nruns=%d)\n",
438  (void*)clck, clck->clocktype, clck->usedefault, clck->nruns);
439 
440  if( clck->nruns == 0 )
441  {
442  /* the clock is not running: convert the clocks timer into seconds */
443  switch( clck->clocktype )
444  {
446  break;
447  case SCIP_CLOCKTYPE_CPU:
448  result = cputime2sec(clck->data.cpuclock.user);
449  break;
450  case SCIP_CLOCKTYPE_WALL:
451  result = walltime2sec(clck->data.wallclock.sec, clck->data.wallclock.usec);
452  break;
453  default:
454  SCIPerrorMessage("invalid clock type\n");
455  SCIPABORT();
456  result = 0.0; /*lint !e527*/
457  }
458  }
459  else
460  {
461 #if defined(_WIN32) || defined(_WIN64)
462  FILETIME creationtime;
463  FILETIME exittime;
464  FILETIME kerneltime;
465  FILETIME usertime;
466 #else
467  struct timeval tp; /*lint !e86*/
468  struct tms now;
469 #endif
470 
471  /* the clock is currently running: we have to add the current time to the clocks timer */
472  switch( clck->clocktype )
473  {
474  case SCIP_CLOCKTYPE_CPU:
475 #if defined(_WIN32) || defined(_WIN64)
476  GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
477  result = cputime2sec(clck->data.cpuclock.user + usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L);
478 #else
479  (void)times(&now);
480  result = cputime2sec(clck->data.cpuclock.user + now.tms_utime);
481 #endif
482  break;
483  case SCIP_CLOCKTYPE_WALL:
484 #if defined(_WIN32) || defined(_WIN64)
485  result = walltime2sec(clck->data.wallclock.sec + time(NULL), 0);
486 #else
487  gettimeofday(&tp, NULL);
488  if( tp.tv_usec + clck->data.wallclock.usec > 1000000 ) /*lint !e115 !e40*/
489  result = walltime2sec(clck->data.wallclock.sec + tp.tv_sec + 1, /*lint !e115 !e40*/
490  (clck->data.wallclock.usec - 1000000) + tp.tv_usec); /*lint !e115 !e40*/
491  else
492  result = walltime2sec(clck->data.wallclock.sec + tp.tv_sec, /*lint !e115 !e40*/
493  clck->data.wallclock.usec + tp.tv_usec); /*lint !e115 !e40*/
494 #endif
495  break;
497  default:
498  SCIPerrorMessage("invalid clock type\n");
499  SCIPABORT();
500  result = 0.0; /*lint !e527*/
501  }
502  }
503 
504  clck->lasttime = result;
505  return result;
506 }
507 
508 /** gets the last validated time of this clock in seconds */
510  SCIP_CLOCK* clck /**< clock timer */
511  )
512 {
513  assert(clck != NULL);
514 
515  return clck->lasttime;
516 }
517 
518 /** sets the used time of this clock in seconds */
520  SCIP_CLOCK* clck, /**< clock timer */
521  SCIP_Real sec /**< time in seconds to set the clock's timer to */
522  )
523 {
524  assert(clck != NULL);
525 
526  SCIPdebugMessage("setting time of clock %p (type %d, usedefault=%u, nruns=%d) to %g\n",
527  (void*)clck, clck->clocktype, clck->usedefault, clck->nruns, sec);
528 
529  /* if the clock type is not yet set, set it to an arbitrary value to be able to store the number */
530  if( clck->clocktype == SCIP_CLOCKTYPE_DEFAULT )
532 
533  switch( clck->clocktype )
534  {
535  case SCIP_CLOCKTYPE_CPU:
536  sec2cputime(sec, &clck->data.cpuclock.user);
537  break;
538 
539  case SCIP_CLOCKTYPE_WALL:
540  sec2walltime(sec, &clck->data.wallclock.sec, &clck->data.wallclock.usec);
541  break;
542 
544  default:
545  SCIPerrorMessage("invalid clock type\n");
546  SCIPABORT();
547  }
548 
549  if( clck->nruns >= 1 )
550  {
551 #if defined(_WIN32) || defined(_WIN64)
552  FILETIME creationtime;
553  FILETIME exittime;
554  FILETIME kerneltime;
555  FILETIME usertime;
556 #else
557  struct timeval tp; /*lint !e86*/
558  struct tms now;
559 #endif
560 
561  /* the clock is currently running: we have to subtract the current time from the new timer value */
562  switch( clck->clocktype )
563  {
564  case SCIP_CLOCKTYPE_CPU:
565 #if defined(_WIN32) || defined(_WIN64)
566  GetProcessTimes(GetCurrentProcess(), &creationtime, &exittime, &kerneltime, &usertime);
567  clck->data.cpuclock.user -= usertime.dwHighDateTime * 42950 + usertime.dwLowDateTime / 100000L;
568 #else
569  (void)times(&now);
570  clck->data.cpuclock.user -= now.tms_utime;
571 #endif
572  break;
573 
574  case SCIP_CLOCKTYPE_WALL:
575 #if defined(_WIN32) || defined(_WIN64)
576  clck->data.wallclock.sec -= time(NULL);
577 #else
578  gettimeofday(&tp, NULL);
579  if( tp.tv_usec > clck->data.wallclock.usec ) /*lint !e115 !e40*/
580  {
581  clck->data.wallclock.sec -= (tp.tv_sec + 1); /*lint !e115 !e40*/
582  clck->data.wallclock.usec += (1000000 - tp.tv_usec); /*lint !e115 !e40*/
583  }
584  else
585  {
586  clck->data.wallclock.sec -= tp.tv_sec; /*lint !e115 !e40*/
587  clck->data.wallclock.usec -= tp.tv_usec; /*lint !e115 !e40*/
588  }
589 #endif
590  break;
591 
593  default:
594  SCIPerrorMessage("invalid clock type\n");
595  SCIPABORT();
596  }
597  }
598 }
599 
600 /** gets current time of day in seconds (standard time zone) */
602  void
603  )
604 {
605 #if defined(_WIN32) || defined(_WIN64)
606  time_t now;
607  now = time(NULL);
608  return (SCIP_Real)(now % (24*3600));
609 #else
610  struct timeval tp; /*lint !e86*/
611 
612  gettimeofday(&tp, NULL);
613 
614  return (SCIP_Real)(tp.tv_sec % (24*3600)) + (SCIP_Real)tp.tv_usec / 1e+6; /*lint !e40 !e115*/
615 #endif
616 }
void SCIPclockEnable(SCIP_CLOCK *clck)
Definition: clock.c:226
void SCIPclockSetType(SCIP_CLOCK *clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:265
SCIP_Bool usedefault
Definition: struct_clock.h:65
static SCIP_Real walltime2sec(long sec, long usec)
Definition: clock.c:68
SCIP_CLOCKTYPE clocktype
Definition: struct_clock.h:64
internal methods for clocks and timing issues
void SCIPclockDisable(SCIP_CLOCK *clck)
Definition: clock.c:238
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:351
enum SCIP_ClockType SCIP_CLOCKTYPE
Definition: type_clock.h:38
#define FALSE
Definition: def.h:73
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:281
#define TRUE
Definition: def.h:72
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
static void clockSetType(SCIP_CLOCK *clck, SCIP_CLOCKTYPE newtype)
Definition: clock.c:117
void SCIPclockInit(SCIP_CLOCK *clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:186
SCIP_Bool enabled
Definition: struct_clock.h:66
#define SCIPdebugMessage
Definition: pub_message.h:87
void SCIPclockEnableOrDisable(SCIP_CLOCK *clck, SCIP_Bool enable)
Definition: clock.c:251
#define BMSfreeMemory(ptr)
Definition: memory.h:137
Definition: heur_padm.c:125
SCIP_Bool SCIPclockIsRunning(SCIP_CLOCK *clck)
Definition: clock.c:418
void SCIPclockSetTime(SCIP_CLOCK *clck, SCIP_Real sec)
Definition: clock.c:519
SCIP_Real lasttime
Definition: struct_clock.h:62
SCIP_Real SCIPclockGetLastTime(SCIP_CLOCK *clck)
Definition: clock.c:509
static void sec2walltime(SCIP_Real sec, long *wallsec, long *wallusec)
Definition: clock.c:101
#define SCIPerrorMessage
Definition: pub_message.h:55
void SCIPclockReset(SCIP_CLOCK *clck)
Definition: clock.c:200
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:429
#define NULL
Definition: lpi_spx1.cpp:155
internal methods for global SCIP settings
SCIP_RETCODE SCIPclockCreate(SCIP_CLOCK **clck, SCIP_CLOCKTYPE clocktype)
Definition: clock.c:161
#define SCIP_Bool
Definition: def.h:70
void SCIPclockFree(SCIP_CLOCK **clck)
Definition: clock.c:176
SCIP_Real SCIPclockGetTimeOfDay(void)
Definition: clock.c:601
static SCIP_Real cputime2sec(clock_t cputime)
Definition: clock.c:44
static void sec2cputime(SCIP_Real sec, clock_t *cputime)
Definition: clock.c:78
static void clockUpdateDefaultType(SCIP_CLOCK *clck, SCIP_CLOCKTYPE defaultclocktype)
Definition: clock.c:148
datastructures for clocks and timing issues
public methods for message output
#define SCIP_Real
Definition: def.h:163
#define BMSallocMemory(ptr)
Definition: memory.h:111
common defines and data types used in all packages of SCIP
#define SCIP_ALLOC(x)
Definition: def.h:381
#define SCIPABORT()
Definition: def.h:342
memory allocation routines