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