Skip to content

Commit

Permalink
* Fixed highspy deadlocking issues
Browse files Browse the repository at this point in the history
* Added GIL acquire for python callbacks
* Added support for user_callback_data
  • Loading branch information
mathgeekcoder committed Sep 10, 2024
1 parent 12d5108 commit e0e0d36
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 30 deletions.
33 changes: 20 additions & 13 deletions src/highs_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,16 +582,26 @@ std::tuple<HighsStatus, int> highs_getRowByName(Highs* h,
return std::make_tuple(status, row);
}


HighsStatus highs_run(Highs* h)
{
py::gil_scoped_release release;
HighsStatus status = h->run();
py::gil_scoped_acquire();
return status;
// Wrap the setCallback function. Pass a lambda wrapper around the python
// function that acquires the GIL and appropriately handle user data passed to
// the callback
HighsStatus highs_setCallback(
Highs* h,
std::function<void(int, const std::string&, const HighsCallbackDataOut*,
HighsCallbackDataIn*, py::handle)>
fn,
py::handle data) {
return h->setCallback(
[fn, data](int callbackType, const std::string& msg,
const HighsCallbackDataOut* dataOut,
HighsCallbackDataIn* dataIn, void* d) {
py::gil_scoped_acquire acquire;
return fn(callbackType, msg, dataOut, dataIn,
py::handle(reinterpret_cast<PyObject*>(d)));
},
data.ptr());
}


PYBIND11_MODULE(_core, m) {
// enum classes
py::enum_<ObjSense>(m, "ObjSense")
Expand Down Expand Up @@ -889,7 +899,7 @@ PYBIND11_MODULE(_core, m) {
.def("writeBasis", &Highs::writeBasis)
.def("postsolve", &highs_postsolve)
.def("postsolve", &highs_mipPostsolve)
.def("run", &highs_run)
.def("run", &Highs::run, py::call_guard<py::gil_scoped_release>())
.def("feasibilityRelaxation",
[](Highs& self, double global_lower_penalty, double global_upper_penalty, double global_rhs_penalty,
py::object local_lower_penalty, py::object local_upper_penalty, py::object local_rhs_penalty) {
Expand Down Expand Up @@ -1021,10 +1031,7 @@ PYBIND11_MODULE(_core, m) {
.def("solutionStatusToString", &Highs::solutionStatusToString)
.def("basisStatusToString", &Highs::basisStatusToString)
.def("basisValidityToString", &Highs::basisValidityToString)
.def(
"setCallback",
static_cast<HighsStatus (Highs::*)(HighsCallbackFunctionType, void*)>(
&Highs::setCallback))
.def("setCallback", &highs_setCallback)
.def("startCallback",
static_cast<HighsStatus (Highs::*)(const HighsCallbackType)>(
&Highs::startCallback))
Expand Down
18 changes: 1 addition & 17 deletions src/highspy/highs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
from threading import Thread, local
import numpy as np

class _ThreadingResult:
def __init__(self):
self.out = None


class Highs(_Highs):
"""
HiGHS solver interface
Expand All @@ -56,13 +51,6 @@ def silent(self, turn_off_output=True):
Disables solver output to the console.
"""
super().setOptionValue("output_flag", not turn_off_output)

def _run(self, res):
res.out = super().run()

def run(self):
return self.solve()


# solve
def solve(self):
Expand All @@ -71,11 +59,7 @@ def solve(self):
Returns:
A HighsStatus object containing the solve status.
"""
res = _ThreadingResult()
t = Thread(target=self._run, args=(res,))
t.start()
t.join()
return res.out
return super().run()

def optimize(self):
"""
Expand Down

0 comments on commit e0e0d36

Please sign in to comment.