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