Repository navigation
[BUG] early_gpufj.cu fails to compile with GCC 14: '*.Lsrc_loc167' not specified in enclosing 'task' #1776
Description
Describe the bug
cpp/src/mip_heuristics/feasibility_jump/early_gpufj.cu fails to compile with newer GCC (14.4.0) as a host compiler for nvcc:
/cpp/src/mip_heuristics/feasibility_jump/early_gpufj.cu: In member function 'void cuopt::mathematical_optimization::mip::early_gpufj_t<i_t, f_t>::start() [with i_t = int; f_t = double]':
/cpp/src/mip_heuristics/feasibility_jump/early_gpufj.cu:66:23: error: '*.Lsrc_loc167' not specified in enclosing 'task'
/cpp/src/mip_heuristics/feasibility_jump/early_gpufj.cu:63:9: note: enclosing 'task'
This was introduced by #1683 (commit 380f7ee), which changed the body of a #pragma omp task default(none) shared(fj_ptr_) ... block at early_gpufj.cu:63-68 from a plain function-call macro to constructing a local RAII guard:
- RAFT_CUDA_TRY(cudaSetDevice(this->device_id_));
+ raft::device_setter guard(this->device_id_);With default(none), GCC requires every entity referenced inside the task body — including compiler-generated temporaries from a local object's constructor/destructor — to be covered by an explicit data-sharing clause. *.Lsrc_loc167 is GCC's internal name for a hidden temporary (likely from source-location tracking inside raft::device_setter's constructor/destructor), which isn't covered by the existing shared(fj_ptr_) clause. -Xcompiler=-Werror on this build turns the resulting warning into a hard error.
I suspect this hasn't shown up on main's regular CI yet because the CI container's GCC version is likely older/less strict than 14.4.0 and doesn't emit this diagnostic — but it reproduces 100% deterministically with GCC 14.4.0, so it's likely to surface there too once the CI image's toolchain advances.
Steps/Code to reproduce bug
- Check out
mainat or after commit 380f7ee (Block Bounded Value Elimination presolving pass for binary problems #1683). - Build
libcuoptlocally with a GCC 14.x toolchain, e.g.:mamba env create -n cuopt_gcc14 -f conda/environments/all_cuda-133_arch-x86_64.yaml conda activate cuopt_gcc14 ./build.sh libcuopt --skip-grpc-build --skip-tests-build --skip-routing-build - Build fails compiling
cuopt_objs.dir/src/mip_heuristics/feasibility_jump/early_gpufj.cu.owith the error above.
Expected behavior
early_gpufj.cu compiles cleanly regardless of GCC version. The #pragma omp task clause at line 63-64 likely needs to be updated (e.g. explicitly listing what the RAII guard touches, or restructuring so the guard doesn't introduce an implicitly-captured temporary under default(none)).
Environment details:
- Environment location: Bare-metal (also reproduced via GitHub Actions
ubuntu-latest-triggered self-hosted CI runner build) - Method of cuOpt install: from source (
./build.sh libcuopt) - Compiler: gcc/g++ (conda-forge gcc 14.4.0-3), CUDA 13.3.73 (nvcc), CMake 4.4.2, Ninja
- GPU arch used for the local repro:
sm_75(auto-detected); CI failure was onsm_70/75/80/86/90a/100f/120a/120multi-arch build
Additional context
First observed while dispatching build.yaml from a feature branch for unrelated testing (a Kitmaker Portal wheel-publishing POC, #1763) — wheel-build-libcuopt and cpp-build both failed with this identical error across multiple matrix jobs (amd64/arm64, CUDA 12.9/13.3) in that same run. Confirmed as a real, deterministic compile failure (not a flaky/cache issue) via a from-scratch local build with no shared cache.
Activity
ramakrishnap-nv commentedon Aug 24, 2026
The issue was already fixed and since branch was not upto date with main, issue was reproduced.
ramakrishnap-nv commentedon Aug 24, 2026
Update / correction: I overstated the reproduction reliability in the original report — this is not as solid as I claimed.
I pulled the latest
main(as of this comment: commitad98d0df, 4 commits ahead of the original repro point) into the branch I was testing from and rebuilt locally with the identical.cuopt_env(GCC 14.4.0, CUDA 13.3, single-archsm_75, same flags). The exact same line (early_gpufj.cu:66, unchanged by the merge) compiled cleanly this time — fulllibcuoptbuild succeeded, no error.Notably, this same merge also touched
feasibility_jump.cuh(whichearly_gpufj.cudirectly includes) — it added a newprobing_cache_t<i_t, f_t>*constructor parameter tofj_tand new members tofj_hyper_parameters_t. That's a plausible explanation: a class-layout/constructor-signature change transitively included byearly_gpufj.cucould alter how the compiler generates exception-handling/destructor metadata inside the#pragma omp taskregion, independent of the flagged line itself.There's also a second variable I didn't control for: the original CI failure was a multi-arch build (
sm_70/75/80/86/90a/100f/120a/120in a singlenvccinvocation), while my local repro used a single-archsm_75build. That's a second plausible reason the diagnostic wouldn't trigger identically.So: the underlying code pattern (a local RAII guard with a nontrivial destructor inside
#pragma omp task default(none) shared(fj_ptr_), without explicitly covering what the guard implicitly touches) is still a real fragility worth fixing on its own merits — but I can no longer say this reproduces deterministically regardless of context. Whoever picks this up should try reproducing with the exact multi-arch--generate-codelist CI uses before concluding anything definitively; my local single-arch repro is not a reliable A/B signal on its own.Apologies for the overstated original claim.
Add Kitmaker Portal wheel publishing via Charon Ferry (#1763)