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   scip_timing.c
17  * @ingroup OTHER_CFILES
18  * @brief  public methods for timing
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Gerald Gamrath
22  * @author Leona Gottwald
23  * @author Stefan Heinz
24  * @author Gregor Hendel
25  * @author Thorsten Koch
26  * @author Alexander Martin
27  * @author Marc Pfetsch
28  * @author Michael Winkler
29  * @author Kati Wolter
30  *
31  * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include "scip/clock.h"
37 #include "scip/conflict.h"
38 #include "scip/debug.h"
39 #include "scip/pub_message.h"
40 #include "scip/reader.h"
41 #include "scip/scip_numerics.h"
42 #include "scip/scip_timing.h"
43 #include "scip/set.h"
44 #include "scip/stat.h"
45 #include "scip/struct_scip.h"
46 #include "scip/struct_set.h"
47 #include "scip/struct_stat.h"
48 
49 /** gets current time of day in seconds (standard time zone)
50  *
51  *  @return the current time of day in seconds (standard time zone).
52  */
SCIPgetTimeOfDay(SCIP * scip)53 SCIP_Real SCIPgetTimeOfDay(
54    SCIP*                 scip                /**< SCIP data structure */
55    )
56 {
57    assert(scip != NULL);
58 
59    return SCIPclockGetTimeOfDay();
60 }
61 
62 /** creates a clock using the default clock type
63  *
64  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
65  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
66  */
SCIPcreateClock(SCIP * scip,SCIP_CLOCK ** clck)67 SCIP_RETCODE SCIPcreateClock(
68    SCIP*                 scip,               /**< SCIP data structure */
69    SCIP_CLOCK**          clck                /**< pointer to clock timer */
70    )
71 {
72    assert(scip != NULL);
73 
74    SCIP_CALL( SCIPclockCreate(clck, SCIP_CLOCKTYPE_DEFAULT) );
75 
76    return SCIP_OKAY;
77 }
78 
79 /** creates a clock counting the CPU user seconds
80  *
81  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
82  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
83  */
SCIPcreateCPUClock(SCIP * scip,SCIP_CLOCK ** clck)84 SCIP_RETCODE SCIPcreateCPUClock(
85    SCIP*                 scip,               /**< SCIP data structure */
86    SCIP_CLOCK**          clck                /**< pointer to clock timer */
87    )
88 {
89    assert(scip != NULL);
90 
91    SCIP_CALL( SCIPclockCreate(clck, SCIP_CLOCKTYPE_CPU) );
92 
93    return SCIP_OKAY;
94 }
95 
96 /** creates a clock counting the wall clock seconds
97  *
98  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
99  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
100  */
SCIPcreateWallClock(SCIP * scip,SCIP_CLOCK ** clck)101 SCIP_RETCODE SCIPcreateWallClock(
102    SCIP*                 scip,               /**< SCIP data structure */
103    SCIP_CLOCK**          clck                /**< pointer to clock timer */
104    )
105 {
106    assert(scip != NULL);
107 
108    SCIP_CALL( SCIPclockCreate(clck, SCIP_CLOCKTYPE_WALL) );
109 
110    return SCIP_OKAY;
111 }
112 
113 /** frees a clock
114  *
115  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
116  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
117  */
SCIPfreeClock(SCIP * scip,SCIP_CLOCK ** clck)118 SCIP_RETCODE SCIPfreeClock(
119    SCIP*                 scip,               /**< SCIP data structure */
120    SCIP_CLOCK**          clck                /**< pointer to clock timer */
121    )
122 {
123    assert(scip != NULL);
124 
125    SCIPclockFree(clck);
126 
127    return SCIP_OKAY;
128 }
129 
130 /** resets the time measurement of a clock to zero and completely stops the clock
131  *
132  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
133  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
134  */
SCIPresetClock(SCIP * scip,SCIP_CLOCK * clck)135 SCIP_RETCODE SCIPresetClock(
136    SCIP*                 scip,               /**< SCIP data structure */
137    SCIP_CLOCK*           clck                /**< clock timer */
138    )
139 {
140    assert(scip != NULL);
141 
142    SCIPclockReset(clck);
143 
144    return SCIP_OKAY;
145 }
146 
147 /** starts the time measurement of a clock
148  *
149  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
150  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
151  */
SCIPstartClock(SCIP * scip,SCIP_CLOCK * clck)152 SCIP_RETCODE SCIPstartClock(
153    SCIP*                 scip,               /**< SCIP data structure */
154    SCIP_CLOCK*           clck                /**< clock timer */
155    )
156 {
157    assert(scip != NULL);
158 
159    SCIPclockStart(clck, scip->set);
160 
161    return SCIP_OKAY;
162 }
163 
164 /** stops the time measurement of a clock
165  *
166  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
167  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
168  */
SCIPstopClock(SCIP * scip,SCIP_CLOCK * clck)169 SCIP_RETCODE SCIPstopClock(
170    SCIP*                 scip,               /**< SCIP data structure */
171    SCIP_CLOCK*           clck                /**< clock timer */
172    )
173 {
174    assert(scip != NULL);
175 
176    SCIPclockStop(clck, scip->set);
177 
178    return SCIP_OKAY;
179 }
180 
181 /** enables or disables all statistic clocks of SCIP concerning plugin statistics,
182  *  LP execution time, strong branching time, etc.
183  *
184  *  Method reads the value of the parameter timing/statistictiming. In order to disable statistic timing,
185  *  set the parameter to FALSE.
186  *
187  *  @note: The (pre-)solving time clocks which are relevant for the output during (pre-)solving
188  *         are not affected by this method
189  *
190  *  @see: For completely disabling all timing of SCIP, consider setting the parameter timing/enabled to FALSE
191  *
192  *  @pre This method can be called if SCIP is in one of the following stages:
193  *       - \ref SCIP_STAGE_INIT
194  *       - \ref SCIP_STAGE_PROBLEM
195  *       - \ref SCIP_STAGE_TRANSFORMING
196  *       - \ref SCIP_STAGE_TRANSFORMED
197  *       - \ref SCIP_STAGE_INITPRESOLVE
198  *       - \ref SCIP_STAGE_PRESOLVING
199  *       - \ref SCIP_STAGE_EXITPRESOLVE
200  *       - \ref SCIP_STAGE_PRESOLVED
201  *       - \ref SCIP_STAGE_INITSOLVE
202  *       - \ref SCIP_STAGE_SOLVING
203  *       - \ref SCIP_STAGE_SOLVED
204  *       - \ref SCIP_STAGE_EXITSOLVE
205  *       - \ref SCIP_STAGE_FREETRANS
206  *
207  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
208  */
SCIPenableOrDisableStatisticTiming(SCIP * scip)209 SCIP_RETCODE SCIPenableOrDisableStatisticTiming(
210    SCIP*                 scip                /**< SCIP data structure */
211    )
212 {
213    SCIP_CALL( SCIPcheckStage(scip, "SCIPenableOrDisableStatisticTiming", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
214 
215    SCIPsetEnableOrDisablePluginClocks(scip->set, scip->set->time_statistictiming);
216 
217    if( scip->set->stage > SCIP_STAGE_INIT )
218    {
219       assert(scip->stat != NULL);
220       SCIPstatEnableOrDisableStatClocks(scip->stat, scip->set->time_statistictiming);
221    }
222    if( scip->set->stage >= SCIP_STAGE_TRANSFORMING )
223    {
224       assert(scip->conflict != NULL);
225       SCIPconflictEnableOrDisableClocks(scip->conflict, scip->set->time_statistictiming);
226    }
227 
228    return SCIP_OKAY;
229 }
230 
231 /** starts the current solving time
232  *
233  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
234  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
235  *
236  *  @pre This method can be called if SCIP is in one of the following stages:
237  *       - \ref SCIP_STAGE_PROBLEM
238  *       - \ref SCIP_STAGE_TRANSFORMING
239  *       - \ref SCIP_STAGE_TRANSFORMED
240  *       - \ref SCIP_STAGE_INITPRESOLVE
241  *       - \ref SCIP_STAGE_PRESOLVING
242  *       - \ref SCIP_STAGE_EXITPRESOLVE
243  *       - \ref SCIP_STAGE_PRESOLVED
244  *       - \ref SCIP_STAGE_INITSOLVE
245  *       - \ref SCIP_STAGE_SOLVING
246  *       - \ref SCIP_STAGE_SOLVED
247  *       - \ref SCIP_STAGE_EXITSOLVE
248  *       - \ref SCIP_STAGE_FREETRANS
249  *
250  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
251  */
SCIPstartSolvingTime(SCIP * scip)252 SCIP_RETCODE SCIPstartSolvingTime(
253    SCIP*                 scip                /**< SCIP data structure */
254    )
255 {
256    SCIP_CALL( SCIPcheckStage(scip, "SCIPstartSolvingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
257 
258    SCIPclockStart(scip->stat->solvingtime, scip->set);
259    SCIPclockStart(scip->stat->solvingtimeoverall, scip->set);
260 
261    return SCIP_OKAY;
262 }
263 
264 /** stops the current solving time in seconds
265  *
266  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
267  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
268  *
269  *  @pre This method can be called if SCIP is in one of the following stages:
270  *       - \ref SCIP_STAGE_PROBLEM
271  *       - \ref SCIP_STAGE_TRANSFORMING
272  *       - \ref SCIP_STAGE_TRANSFORMED
273  *       - \ref SCIP_STAGE_INITPRESOLVE
274  *       - \ref SCIP_STAGE_PRESOLVING
275  *       - \ref SCIP_STAGE_EXITPRESOLVE
276  *       - \ref SCIP_STAGE_PRESOLVED
277  *       - \ref SCIP_STAGE_INITSOLVE
278  *       - \ref SCIP_STAGE_SOLVING
279  *       - \ref SCIP_STAGE_SOLVED
280  *       - \ref SCIP_STAGE_EXITSOLVE
281  *       - \ref SCIP_STAGE_FREETRANS
282  *
283  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
284  */
SCIPstopSolvingTime(SCIP * scip)285 SCIP_RETCODE SCIPstopSolvingTime(
286    SCIP*                 scip                /**< SCIP data structure */
287    )
288 {
289    SCIP_CALL( SCIPcheckStage(scip, "SCIPstopSolvingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
290 
291    SCIPclockStop(scip->stat->solvingtime, scip->set);
292    SCIPclockStop(scip->stat->solvingtimeoverall, scip->set);
293 
294    return SCIP_OKAY;
295 }
296 
297 /** gets the measured time of a clock in seconds
298  *
299  *  @return the measured time of a clock in seconds.
300  */
SCIPgetClockTime(SCIP * scip,SCIP_CLOCK * clck)301 SCIP_Real SCIPgetClockTime(
302    SCIP*                 scip,               /**< SCIP data structure */
303    SCIP_CLOCK*           clck                /**< clock timer */
304    )
305 {
306    assert(scip != NULL);
307 
308    return SCIPclockGetTime(clck);
309 }
310 
311 /** sets the measured time of a clock to the given value in seconds
312  *
313  *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
314  *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
315  */
SCIPsetClockTime(SCIP * scip,SCIP_CLOCK * clck,SCIP_Real sec)316 SCIP_RETCODE SCIPsetClockTime(
317    SCIP*                 scip,               /**< SCIP data structure */
318    SCIP_CLOCK*           clck,               /**< clock timer */
319    SCIP_Real             sec                 /**< time in seconds to set the clock's timer to */
320    )
321 {
322    assert(scip != NULL);
323 
324    SCIPclockSetTime(clck, sec);
325 
326    return SCIP_OKAY;
327 }
328 
329 /** gets the current total SCIP time in seconds, possibly accumulated over several problems.
330  *
331  *  @return the current total SCIP time in seconds, ie. the total time since the SCIP instance has been created
332  */
SCIPgetTotalTime(SCIP * scip)333 SCIP_Real SCIPgetTotalTime(
334    SCIP*                 scip                /**< SCIP data structure */
335    )
336 {
337    assert(scip != NULL);
338 
339    return SCIPclockGetTime(scip->totaltime);
340 }
341 
342 /** gets the current solving time in seconds
343  *
344  *  @return the current solving time in seconds.
345  *
346  *  @pre This method can be called if SCIP is in one of the following stages:
347  *       - \ref SCIP_STAGE_PROBLEM
348  *       - \ref SCIP_STAGE_TRANSFORMING
349  *       - \ref SCIP_STAGE_TRANSFORMED
350  *       - \ref SCIP_STAGE_INITPRESOLVE
351  *       - \ref SCIP_STAGE_PRESOLVING
352  *       - \ref SCIP_STAGE_EXITPRESOLVE
353  *       - \ref SCIP_STAGE_PRESOLVED
354  *       - \ref SCIP_STAGE_INITSOLVE
355  *       - \ref SCIP_STAGE_SOLVING
356  *       - \ref SCIP_STAGE_SOLVED
357  *
358  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
359  */
SCIPgetSolvingTime(SCIP * scip)360 SCIP_Real SCIPgetSolvingTime(
361    SCIP*                 scip                /**< SCIP data structure */
362    )
363 {
364    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetSolvingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
365 
366    return SCIPclockGetTime(scip->stat->solvingtime);
367 }
368 
369 /** gets the current reading time in seconds
370  *
371  *  @return the current reading time in seconds.
372  *
373  *  @pre This method can be called if SCIP is in one of the following stages:
374  *       - \ref SCIP_STAGE_PROBLEM
375  *       - \ref SCIP_STAGE_TRANSFORMING
376  *       - \ref SCIP_STAGE_TRANSFORMED
377  *       - \ref SCIP_STAGE_INITPRESOLVE
378  *       - \ref SCIP_STAGE_PRESOLVING
379  *       - \ref SCIP_STAGE_EXITPRESOLVE
380  *       - \ref SCIP_STAGE_PRESOLVED
381  *       - \ref SCIP_STAGE_INITSOLVE
382  *       - \ref SCIP_STAGE_SOLVING
383  *       - \ref SCIP_STAGE_SOLVED
384  *
385  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
386  */
SCIPgetReadingTime(SCIP * scip)387 SCIP_Real SCIPgetReadingTime(
388    SCIP*                 scip                /**< SCIP data structure */
389    )
390 {
391    SCIP_Real readingtime;
392    int r;
393 
394    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetReadingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
395 
396    readingtime = 0.0;
397 
398    /* sum up the reading time of all readers */
399    for( r = 0; r < scip->set->nreaders; ++r )
400    {
401       assert(scip->set->readers[r] != NULL);
402       assert(!SCIPisNegative(scip, SCIPreaderGetReadingTime(scip->set->readers[r])));
403       readingtime += SCIPreaderGetReadingTime(scip->set->readers[r]);
404    }
405 
406    return readingtime;
407 }
408 
409 /** gets the current presolving time in seconds
410  *
411  *  @return the current presolving time in seconds.
412  *
413  *  @pre This method can be called if SCIP is in one of the following stages:
414  *       - \ref SCIP_STAGE_INITPRESOLVE
415  *       - \ref SCIP_STAGE_PRESOLVING
416  *       - \ref SCIP_STAGE_EXITPRESOLVE
417  *       - \ref SCIP_STAGE_PRESOLVED
418  *       - \ref SCIP_STAGE_INITSOLVE
419  *       - \ref SCIP_STAGE_SOLVING
420  *       - \ref SCIP_STAGE_SOLVED
421  *
422  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
423  */
SCIPgetPresolvingTime(SCIP * scip)424 SCIP_Real SCIPgetPresolvingTime(
425    SCIP*                 scip                /**< SCIP data structure */
426    )
427 {
428    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetPresolvingTime", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
429 
430    return SCIPclockGetTime(scip->stat->presolvingtime);
431 }
432 
433 /** gets the time need to solve the first LP in the root node
434  *
435  *  @return the solving time for the first LP in the root node in seconds.
436  *
437  *  @pre This method can be called if SCIP is in one of the following stages:
438  *       - \ref SCIP_STAGE_TRANSFORMING
439  *       - \ref SCIP_STAGE_TRANSFORMED
440  *       - \ref SCIP_STAGE_INITPRESOLVE
441  *       - \ref SCIP_STAGE_PRESOLVING
442  *       - \ref SCIP_STAGE_EXITPRESOLVE
443  *       - \ref SCIP_STAGE_PRESOLVED
444  *       - \ref SCIP_STAGE_INITSOLVE
445  *       - \ref SCIP_STAGE_SOLVING
446  *       - \ref SCIP_STAGE_SOLVED
447  *
448  *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
449  */
SCIPgetFirstLPTime(SCIP * scip)450 SCIP_Real SCIPgetFirstLPTime(
451    SCIP*                 scip                /**< SCIP data structure */
452    )
453 {
454    SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetFirstLPTime", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
455 
456    return scip->stat->firstlptime;
457 }
458