diff --git a/ortools/linear_solver/scip_interface.cc b/ortools/linear_solver/scip_interface.cc index 96826f8b25..4f97db35fa 100644 --- a/ortools/linear_solver/scip_interface.cc +++ b/ortools/linear_solver/scip_interface.cc @@ -174,6 +174,10 @@ util::Status SCIPInterface::CreateSCIP() { } // Default clock type. We use wall clock time because getting CPU user seconds // involves calling times() which is very expensive. + // NOTE(user): Also, time limit based on CPU user seconds is *NOT* thread + // safe. We observed that different instances of SCIP running concurrently + // in different threads consume the time limit *together*. E.g., 2 threads + // running SCIP with time limit 10s each will both terminate after ~5s. RETURN_IF_SCIP_ERROR( SCIPsetIntParam(scip_, "timing/clocktype", SCIP_CLOCKTYPE_WALL)); RETURN_IF_SCIP_ERROR(SCIPcreateProb(scip_, solver_->name_.c_str(), nullptr, diff --git a/ortools/linear_solver/scip_proto_solver.cc b/ortools/linear_solver/scip_proto_solver.cc index eda917960c..952e935577 100644 --- a/ortools/linear_solver/scip_proto_solver.cc +++ b/ortools/linear_solver/scip_proto_solver.cc @@ -700,6 +700,14 @@ util::StatusOr ScipSolveProto( response.set_status_str(parameters_status.error_message()); return response; } + // Default clock type. We use wall clock time because getting CPU user seconds + // involves calling times() which is very expensive. + // NOTE(user): Also, time limit based on CPU user seconds is *NOT* thread + // safe. We observed that different instances of SCIP running concurrently + // in different threads consume the time limit *together*. E.g., 2 threads + // running SCIP with time limit 10s each will both terminate after ~5s. + RETURN_IF_SCIP_ERROR( + SCIPsetIntParam(scip, "timing/clocktype", SCIP_CLOCKTYPE_WALL)); if (request.solver_time_limit_seconds() > 0 && request.solver_time_limit_seconds() < 1e20) { RETURN_IF_SCIP_ERROR(SCIPsetRealParam(scip, "limits/time",