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