Skip to content

Commit 60f806f

Browse files
authored
Merge pull request #3141 from ERGO-Code/od/resetGlobalScheduler
Remove resetGlobalScheduler calls from C API
2 parents 834f299 + 8985537 commit 60f806f

5 files changed

Lines changed: 65 additions & 40 deletions

File tree

.github/julia/build_tarballs.jl

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ version = VersionNumber(ENV["HIGHS_RELEASE"])
1212
sources = [GitSource(ENV["HIGHS_URL"], ENV["HIGHS_COMMIT"])]
1313

1414
script = raw"""
15-
export BUILD_SHARED="ON"
16-
export BUILD_STATIC="OFF"
17-
1815
cd $WORKSPACE/srcdir/HiGHS
1916
2017
# Remove system CMake to use the jll version
@@ -23,19 +20,21 @@ apk del cmake
2320
rm -rf build
2421
mkdir build
2522
26-
# Do fully static build only on Windows
27-
if [[ "${BUILD_SHARED}" == "OFF" ]] && [[ "${target}" == *-mingw* ]]; then
28-
export CXXFLAGS="-static"
23+
if [[ "${target}" == *-mingw* ]]; then
24+
LBT=blastrampoline-5
25+
else
26+
LBT=blastrampoline
2927
fi
3028
3129
cmake -S . -B build \
3230
-DCMAKE_INSTALL_PREFIX=${prefix} \
3331
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN} \
3432
-DCMAKE_BUILD_TYPE=Release \
35-
-DBUILD_SHARED_LIBS=${BUILD_SHARED} \
36-
-DZLIB_USE_STATIC_LIBS=${BUILD_STATIC} \
37-
-DHIPO=ON -DBUILD_SHARED_EXTRAS_LIB=OFF \
38-
-DBLAS_LIBRARIES="${libdir}/libopenblas.${dlext}"
33+
-DBUILD_SHARED_LIBS=ON \
34+
-DHIPO=ON \
35+
-DBUILD_SHARED_EXTRAS_LIB=OFF \
36+
-DBLA_VENDOR=blastrampoline \
37+
-DBLAS_LIBRARIES=\"${LBT}\"
3938
4039
if [[ "${target}" == *-linux-* ]]; then
4140
make -C build -j ${nproc}
@@ -62,7 +61,7 @@ platforms = expand_cxxstring_abis(platforms)
6261
dependencies = [
6362
Dependency("CompilerSupportLibraries_jll"),
6463
Dependency("Zlib_jll"),
65-
Dependency("OpenBLAS32_jll"),
64+
Dependency("libblastrampoline_jll"),
6665
HostBuildDependency(PackageSpec(; name="CMake_jll")),
6766
]
6867

@@ -76,5 +75,5 @@ build_tarballs(
7675
products,
7776
dependencies;
7877
preferred_gcc_version = v"11",
79-
julia_compat = "1.6",
78+
julia_compat = "1.10",
8079
)

.github/workflows/julia-tests.yml

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
name: JuliaCompileAndTest
2-
32
on: [push, pull_request]
4-
# needed to allow julia-actions/cache to delete old caches that it has created
5-
63
concurrency:
74
group: ${{ github.workflow }}-${{ github.ref }}
85
cancel-in-progress: true
9-
6+
# needed to allow julia-actions/cache to delete old caches that it has created
107
permissions:
118
actions: write
129
contents: read
@@ -18,7 +15,7 @@ jobs:
1815
matrix:
1916
triplet: ['x86_64-linux-gnu-cxx11', 'aarch64-apple-darwin', 'x86_64-w64-mingw32-cxx11']
2017
steps:
21-
- uses: actions/checkout@v6
18+
- uses: actions/checkout@v7
2219
- uses: julia-actions/setup-julia@v3
2320
with:
2421
version: "1.7"
@@ -64,7 +61,7 @@ jobs:
6461
os: 'windows-latest'
6562
arch: x64
6663
steps:
67-
- uses: actions/checkout@v6
64+
- uses: actions/checkout@v7
6865
- uses: julia-actions/setup-julia@v3
6966
with:
7067
version: "1.10"
@@ -106,18 +103,7 @@ jobs:
106103
"$(m[1]) = \"$(dir)\"\n",
107104
)
108105
Pkg.develop(; path = joinpath(ENV["GITHUB_WORKSPACE"], "HiGHS_jll"))
109-
- shell: julia --color=yes {0}
110-
run: |
111-
import HiGHS_jll
112-
file = joinpath(ENV["GITHUB_WORKSPACE"], "check", "instances", "flugpl.mps")
113-
run(`$(HiGHS_jll.highs()) --solver=hipo $file`)
114-
run(`$(HiGHS_jll.highs()) $file`)
115106
- shell: julia --color=yes {0}
116107
run: |
117108
using Pkg
118-
# HiGHS uses (N+1)/2 threads. HiGHS.jl parallelises the tests and, in
119-
# the default setting, it may use up to 4 parallel jobs. This means
120-
# HiGHS may attempt to start up to 2(N+1) threads and we get unhandled
121-
# exceptions on macOS and a SIGTERM on linux. To avoid these errors,
122-
# opt out of running the tests in parallel.
123-
Pkg.test("HiGHS"; test_args=["--parallel=false"])
109+
Pkg.test("HiGHS")

check/TestHighsParallel.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <iostream>
88

99
#include "catch.hpp"
10+
#include "interfaces/highs_c_api.h"
1011
#include "matrix_multiplication.hpp"
1112
#include "parallel/HighsParallel.h"
1213

@@ -305,4 +306,52 @@ TEST_CASE("CancelNestedTasks", "[parallel]") {
305306
}
306307

307308
HighsTaskExecutor::shutdown();
309+
}
310+
311+
TEST_CASE("ParallelCApi", "[parallel]") {
312+
// This test exposes a failure in the C api when creating and destroying Highs
313+
// instances on separate threads.
314+
// One thread solves a mip, while the other loses some time before destroying
315+
// the instance. If this causes the scheduler to be terminated (i.e., if
316+
// Highs_destroy calls resetGlobalScheduler) while the first thread is still
317+
// using it, the first thread may crash, hang, or terminate with wrong
318+
// results.
319+
320+
highs::parallel::initialize_scheduler();
321+
322+
std::string model = std::string(HIGHS_DIR) + "/check/instances/egout.mps";
323+
const double expected_obj = 568.1007;
324+
double actual_obj;
325+
double total = 0;
326+
327+
{
328+
highs::parallel::TaskGroup tg;
329+
330+
tg.spawn([&]() {
331+
void* highs = Highs_create();
332+
Highs_setBoolOptionValue(highs, "output_flag", dev_run);
333+
Highs_setStringOptionValue(highs, "parallel", "on");
334+
Highs_readModel(highs, model.c_str());
335+
Highs_run(highs);
336+
Highs_getDoubleInfoValue(highs, "objective_function_value", &actual_obj);
337+
Highs_destroy(highs);
338+
});
339+
340+
tg.spawn([&]() {
341+
void* highs = Highs_create();
342+
for (int i = 0; i < 1e6; ++i) {
343+
total += (double)i * i * i;
344+
}
345+
Highs_destroy(highs);
346+
});
347+
348+
tg.taskWait();
349+
350+
REQUIRE(total > 1e18);
351+
REQUIRE(std::abs(actual_obj - expected_obj) / std::abs(expected_obj) <
352+
1e-4);
353+
}
354+
// TaskGroup destructor must be called before scheduler is killed
355+
356+
HighsTaskExecutor::shutdown(true);
308357
}

examples/call_highs_from_c_minimal.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,5 +655,6 @@ int main() {
655655
minimal_api();
656656
minimal_api_qp();
657657
full_api();
658+
Highs_resetGlobalScheduler(1);
658659
return 0;
659660
}

highs/interfaces/highs_c_api.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ HighsInt Highs_lpCall(const HighsInt num_col, const HighsInt num_row,
6161
if (copy_row_basis) row_basis_status[i] = (HighsInt)basis.row_status[i];
6262
}
6363
}
64-
65-
highs.resetGlobalScheduler(true);
66-
6764
return (HighsInt)status;
6865
}
6966

@@ -106,9 +103,6 @@ HighsInt Highs_mipCall(const HighsInt num_col, const HighsInt num_row,
106103
row_value[i] = solution.row_value[i];
107104
}
108105
}
109-
110-
highs.resetGlobalScheduler(true);
111-
112106
return (HighsInt)status;
113107
}
114108

@@ -165,16 +159,12 @@ HighsInt Highs_qpCall(
165159
if (copy_row_basis) row_basis_status[i] = (HighsInt)basis.row_status[i];
166160
}
167161
}
168-
169-
highs.resetGlobalScheduler(true);
170-
171162
return (HighsInt)status;
172163
}
173164

174165
void* Highs_create(void) { return new Highs(); }
175166

176167
void Highs_destroy(void* highs) {
177-
Highs::resetGlobalScheduler(true);
178168
delete (Highs*)highs;
179169
}
180170

0 commit comments

Comments
 (0)