Skip to content

[BUG] early_gpufj.cu fails to compile with GCC 14: '*.Lsrc_loc167' not specified in enclosing 'task' #1776

Closed

Description

@ramakrishnap-nv

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

  1. Check out main at or after commit 380f7ee (Block Bounded Value Elimination presolving pass for binary problems #1683).
  2. Build libcuopt locally 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
    
  3. Build fails compiling cuopt_objs.dir/src/mip_heuristics/feasibility_jump/early_gpufj.cu.o with 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 on sm_70/75/80/86/90a/100f/120a/120 multi-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.

Introduced by #1683 / commit 380f7ee.

Activity

  1. ramakrishnap-nv commented on Aug 24, 2026

    @ramakrishnap-nv
    CollaboratorAuthor

    The issue was already fixed and since branch was not upto date with main, issue was reproduced.

  2. ramakrishnap-nv commented on Aug 24, 2026

    @ramakrishnap-nv
    CollaboratorAuthor

    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: commit ad98d0df, 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-arch sm_75, same flags). The exact same line (early_gpufj.cu:66, unchanged by the merge) compiled cleanly this time — full libcuopt build succeeded, no error.

    Notably, this same merge also touched feasibility_jump.cuh (which early_gpufj.cu directly includes) — it added a new probing_cache_t<i_t, f_t>* constructor parameter to fj_t and new members to fj_hyper_parameters_t. That's a plausible explanation: a class-layout/constructor-signature change transitively included by early_gpufj.cu could alter how the compiler generates exception-handling/destructor metadata inside the #pragma omp task region, 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/120 in a single nvcc invocation), while my local repro used a single-arch sm_75 build. 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-code list 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions