cuOpt.jl MOI wrapper: unhandled 'Invalid argument' from GetPrimalSolution/GetDualSolution fails 36 conformance tests every nightly run

未关闭
#1,832 3 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 1 天内回复

@rg20 已经在做这个了。

开始于 2026年8月31日。

评估

这个 Issue 还没有评估数据。

描述

bug

Summary

cuOpt.jl's MOI wrapper optimize! unconditionally calls cuOptGetPrimalSolution/cuOptGetDualSolution after solving, without checking termination status first. This throws an "Invalid argument" C-API error (rather than returning gracefully) whenever:

  • the problem was declared infeasible/unbounded (often at presolve, so no primal solution buffer exists), or
  • the problem has quadratic/second-order-cone constraints (duals are documented as not returned for these: "Dual variables for problems with quadratic constraints not returned.")

This causes the thirdparty jump (Julia MOI conformance) test step to fail on every nightly wheel-tests-cuopt job, across all GPU/driver/dependency combinations, while all Python test suites (LP/MILP/QP/routing/classification) pass cleanly.

Observed in

Nightly test.yaml run 33361623272 (main @ d3af87e3, 2026-08-31) — all wheel-tests-cuopt matrix jobs report thirdparty jump as a failed step, consistently: 1397 passed, 0 failed, 36 errored, 0 broken.

This is not a one-off: test.yaml has failed with this same 36 errored Julia MOI signature on nearly every nightly run since at least 2026-08-13 (3+ weeks), e.g. runs 33295253627, 33237039486, 33154333403, 33053460319, 32936929656, 32814253431.

Distinct from the previously-fixed #1485 (a Julia 1.12.x JIT SIGSEGV on MOI.delete for bridged SOC constraints) — that was a crash bug fixed via an exclude list; this is a separate, still-open error-handling gap in the wrapper's result-fetching path (no crash, just an unhandled C-API error surfaced as a Julia test error).

Example stack trace

test_conic_SecondOrderCone_negative_initial_bound: Error During Test at .../MathOptInterface/Test/Test.jl:264
  Got exception outside of a @test
  Invalid argument in cuOptGetDualSolution.
  Stacktrace:
    [1] error(s::String) @ Base ./error.jl:44
    [2] _check_ret(ret::Int32, msg::String) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:438
    [3] optimize!(model::cuOpt.Optimizer) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:1316
test_infeasible_MAX_SENSE: Error During Test at .../MathOptInterface/Test/Test.jl:264
  Got exception outside of a @test
  Invalid argument in cuOptGetPrimalSolution.
  Stacktrace:
    [1] error(s::String) @ Base ./error.jl:44
    [2] _check_ret(ret::Int32, msg::String) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:438
    [3] optimize!(model::cuOpt.Optimizer) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:1307

Affected tests (36, same set every night)

test_conic_SecondOrderCone_negative_initial_bound
test_conic_SecondOrderCone_negative_post_bound
test_conic_SecondOrderCone_nonnegative_initial_bound
test_constraint_ZeroOne_bounds_3
test_infeasible_affine_MAX_SENSE
test_infeasible_affine_MAX_SENSE_offset
test_infeasible_affine_MIN_SENSE
test_infeasible_affine_MIN_SENSE_offset
test_infeasible_MAX_SENSE
test_infeasible_MAX_SENSE_offset
test_infeasible_MIN_SENSE
test_infeasible_MIN_SENSE_offset
test_linear_DUAL_INFEASIBLE
test_linear_DUAL_INFEASIBLE_2
test_linear_INFEASIBLE
test_linear_INFEASIBLE_2
test_linear_Semicontinuous_integration
test_modification_coef_scalar_objective
test_modification_const_scalar_objective
test_modification_delete_variables_in_a_batch
test_modification_set_singlevariable_lessthan
test_modification_transform_singlevariable_lessthan
test_objective_FEASIBILITY_SENSE_clears_objective
test_objective_ObjectiveFunction_constant
test_objective_ObjectiveFunction_duplicate_terms
test_objective_qp_ObjectiveFunction_edge_cases
test_objective_qp_ObjectiveFunction_zero_ofdiag
test_solve_ObjectiveBound_MAX_SENSE_LP
test_solve_ObjectiveBound_MIN_SENSE_LP
test_solve_TerminationStatus_DUAL_INFEASIBLE
test_unbounded_MAX_SENSE
test_unbounded_MAX_SENSE_offset
test_unbounded_MIN_SENSE
test_unbounded_MIN_SENSE_offset
test_variable_solve_with_lowerbound
test_variable_solve_with_upperbound

Suggested fix

In cuOpt.jl's optimize! (MOI_wrapper.jl, around lines 1300-1320), check the termination/solve status before calling cuOptGetPrimalSolution / cuOptGetDualSolution:

  • Skip primal retrieval when the reported status is infeasible/unbounded/presolve-determined.
  • Skip dual retrieval when the model has quadratic/SOC constraints (consistent with the documented C-API behavior).

Impact

Every nightly wheel-tests-cuopt job across all GPU/driver/dependency combinations is marked failed due to this, masking any other genuine regression in that same CI signal. All other nightly test suites (Python LP/MILP/QP/routing/classification) are green.

主要语言
Cuda
星标
1.1k
派生
255
平均合并
1 天 22 小时
30 天内合并 PR
102

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

NVIDIA/cuopt 的其他 Issue

查看 NVIDIA/cuopt 的全部 Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。