You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Querying dual of a FixRef is very slow on larger models #17
I am running an LP model with ~250K variables and ~300K constraints as a test case for CuPDLPx. When I tried to query a dual value from the fixed constraint reference on a variable, it took 9 minutes to query a single dual value. I did test querying the dual of a fixed constraint reference on a simpler model that was solved with CuPDLPx, and it worked fine. For reference, the .lp file of the model I am using can be found at the githup repo here (it won't upload directly on the issue, so apologies for the roundabout way of uploading). The following code loads the .lp file and recreates the problem. Any ideas why the dual is not being returned quickly?
using JuMP, CuPDLPx
m =read_from_file((@__DIR__)*"/test_model.lp")
set_optimizer(m, CuPDLPx.Optimizer)
set_optimizer_attribute(m, "verbose", true)
set_optimizer_attribute(m, "l_inf_ruiz_iterations", 0)
set_optimizer_attribute(m, "iteration_limit", 1e5)
optimize!(m)
println(solution_summary(m))
fixed_variables = []
for v inall_variables(m)
ifis_fixed(v)
push!(fixed_variables, v)
endendprintln("TRYING TO GET DUAL VALUE")
@timedual(FixRef(fixed_variables[1]))
I don't understand. Zedong the code you've referenced is for an affine constraint. Do you support returning duals from fixed variables? (VariableIndex-in-EqualTo)?
And @dlcole3 does your example even return the correct solution?
My bad. I didn’t notice it was the reduced cost. cuPDLPx does return the reduced cost in the result, but the current MOI_wrapper doesn’t support it yet.
function MOI.get(
optimizer::Optimizer,
attr::MOI.ConstraintDual,
ci::MOI.ConstraintIndex{MOI.VariableIndex,S},
) where {S<:MOI.AbstractSet}
MOI.check_result_index_bounds(optimizer, attr)
return ???
end
@ZedongPeng I have updated to use the main branch with the recent PR, and it is working great now. Thank you so much for your quick response in getting this working!
Activity
ZedongPeng commentedon Jan 28, 2026
Hi @dlcole3 — thanks for reporting this. I can reproduce it locally as well.
Since cuPDLPx returns results on the CPU, this doesn’t seem to be caused by CPU↔GPU transfer overhead.
My guess is that the bottleneck is in the following function in the
MOI_wrapper—the current approach might not be very efficient.Hi @blegat and @odow: do you have suggestions or prior experience improving this?
CuPDLPx.jl/src/MOI_wrapper.jl
Lines 451 to 459 in bc521d6
--------------------------------------------------------------------------------------- cuPDLPx v0.2.5 A GPU-Accelerated First-Order LP Solver (c) Haihao Lu, Massachusetts Institute of Technology, 2025 --------------------------------------------------------------------------------------- problem: 308001 rows, 234096 columns, 1137952 nonzeros settings: iter_limit : 100000 time_limit : 3600.00 sec eps_opt : 1.0e-04 eps_feas : 1.0e-04 l_inf_ruiz_iter : 0 Running presolver (PSLP v0.0.4)... status : REDUCED presolve time : 0.261 sec reduced problem : 157221 rows, 130861 columns, 684356 nonzeros Preconditioning Pock-Chambolle scaling (alpha=1.0000) Bound-objective scaling --------------------------------------------------------------------------------------- runtime | objective | absolute residuals | relative residuals iter time | pr obj du obj | pr res du res gap | pr res du res gap --------------------------------------------------------------------------------------- 0 0.0e+00 | 0.0e+00 0.0e+00 | 0.0e+00 0.0e+00 0.0e+00 | 0.0e+00 0.0e+00 0.0e+00 200 0.0e+00 | 8.1e+02 1.3e+03 | 1.6e+01 7.0e-01 5.1e+02 | 4.9e-03 4.4e-03 2.4e-01 400 1.7e-02 | 8.6e+02 9.1e+02 | 6.9e+00 1.6e-01 4.8e+01 | 2.1e-03 1.0e-03 2.7e-02 600 2.4e-02 | 8.5e+02 8.5e+02 | 7.3e+00 6.0e-02 2.8e+00 | 2.2e-03 3.7e-04 1.6e-03 800 3.1e-02 | 8.3e+02 8.3e+02 | 4.6e+00 4.0e-02 2.7e+00 | 1.4e-03 2.5e-04 1.6e-03 1000 3.8e-02 | 8.2e+02 8.3e+02 | 4.1e+00 2.6e-02 2.1e+00 | 1.2e-03 1.6e-04 1.3e-03 1200 4.5e-02 | 8.2e+02 8.2e+02 | 3.8e+00 2.2e-02 2.9e+00 | 1.1e-03 1.4e-04 1.8e-03 1400 5.2e-02 | 8.1e+02 8.2e+02 | 2.7e+00 1.8e-02 5.2e+00 | 8.2e-04 1.1e-04 3.2e-03 1600 5.9e-02 | 8.1e+02 8.1e+02 | 3.2e+00 9.2e-03 1.1e+00 | 9.7e-04 5.7e-05 7.0e-04 1800 6.6e-02 | 8.0e+02 8.0e+02 | 2.8e+00 5.9e-03 2.1e+00 | 8.6e-04 3.7e-05 1.3e-03 2000 7.2e-02 | 8.0e+02 8.0e+02 | 2.4e+00 4.8e-03 1.6e+00 | 7.2e-04 3.0e-05 1.0e-03 2200 7.9e-02 | 8.0e+02 8.0e+02 | 1.7e+00 4.1e-03 7.6e-02 | 5.2e-04 2.5e-05 4.8e-05 2400 8.6e-02 | 8.0e+02 8.0e+02 | 2.3e+00 2.8e-03 4.7e-01 | 7.0e-04 1.7e-05 2.9e-04 2600 9.3e-02 | 8.0e+02 8.0e+02 | 2.0e+00 2.4e-03 1.0e+00 | 5.9e-04 1.5e-05 6.4e-04 2800 1.0e-01 | 8.0e+02 8.0e+02 | 1.5e+00 2.0e-03 1.0e+00 | 4.5e-04 1.3e-05 6.4e-04 3000 1.1e-01 | 8.0e+02 8.0e+02 | 1.3e+00 1.8e-03 1.1e-01 | 3.9e-04 1.1e-05 6.9e-05 3200 1.1e-01 | 8.0e+02 8.0e+02 | 1.2e+00 1.6e-03 1.5e-01 | 3.7e-04 9.8e-06 9.4e-05 3400 1.2e-01 | 8.0e+02 8.0e+02 | 1.1e+00 1.5e-03 3.0e-01 | 3.2e-04 9.3e-06 1.9e-04 3600 1.3e-01 | 8.0e+02 8.0e+02 | 9.8e-01 1.3e-03 2.3e-01 | 3.0e-04 8.3e-06 1.4e-04 3800 1.3e-01 | 8.0e+02 8.0e+02 | 9.2e-01 8.7e-04 4.0e-01 | 2.8e-04 5.4e-06 2.5e-04 4000 1.4e-01 | 8.0e+02 8.0e+02 | 8.9e-01 8.1e-04 5.3e-01 | 2.7e-04 5.0e-06 3.3e-04 4200 1.5e-01 | 8.0e+02 8.0e+02 | 9.1e-01 7.5e-04 7.4e-01 | 2.7e-04 4.6e-06 4.6e-04 4400 1.5e-01 | 8.0e+02 8.0e+02 | 9.3e-01 6.8e-04 8.3e-01 | 2.8e-04 4.2e-06 5.2e-04 4600 1.6e-01 | 8.0e+02 8.0e+02 | 9.3e-01 6.1e-04 9.3e-01 | 2.8e-04 3.8e-06 5.8e-04 4800 1.7e-01 | 8.0e+02 8.0e+02 | 9.2e-01 5.3e-04 8.3e-01 | 2.8e-04 3.3e-06 5.2e-04 5000 1.7e-01 | 8.0e+02 8.0e+02 | 9.2e-01 5.0e-04 7.6e-01 | 2.8e-04 3.1e-06 4.8e-04 5200 1.8e-01 | 8.0e+02 8.0e+02 | 9.2e-01 4.7e-04 8.5e-01 | 2.8e-04 2.9e-06 5.3e-04 5400 1.9e-01 | 8.0e+02 8.0e+02 | 9.0e-01 4.1e-04 9.6e-01 | 2.7e-04 2.5e-06 6.0e-04 5600 2.0e-01 | 8.0e+02 8.0e+02 | 8.6e-01 3.9e-04 9.7e-01 | 2.6e-04 2.4e-06 6.1e-04 5800 2.0e-01 | 8.0e+02 8.0e+02 | 8.0e-01 3.8e-04 8.1e-01 | 2.4e-04 2.4e-06 5.1e-04 6000 2.1e-01 | 8.0e+02 8.0e+02 | 7.8e-01 2.7e-04 7.4e-01 | 2.3e-04 1.7e-06 4.7e-04 6200 2.2e-01 | 8.0e+02 8.0e+02 | 7.8e-01 2.3e-04 8.4e-01 | 2.4e-04 1.4e-06 5.3e-04 6400 2.2e-01 | 8.0e+02 8.0e+02 | 7.7e-01 2.0e-04 9.2e-01 | 2.3e-04 1.3e-06 5.8e-04 6600 2.3e-01 | 8.0e+02 8.0e+02 | 7.5e-01 1.7e-04 1.0e+00 | 2.3e-04 1.1e-06 6.3e-04 6800 2.4e-01 | 8.0e+02 8.0e+02 | 7.3e-01 1.6e-04 1.0e+00 | 2.2e-04 1.0e-06 6.4e-04 7000 2.4e-01 | 8.0e+02 8.0e+02 | 7.1e-01 1.6e-04 1.1e+00 | 2.1e-04 9.8e-07 6.6e-04 7200 2.5e-01 | 8.0e+02 8.0e+02 | 7.1e-01 1.5e-04 1.1e+00 | 2.1e-04 9.6e-07 6.6e-04 7400 2.6e-01 | 8.0e+02 8.0e+02 | 7.0e-01 1.5e-04 1.0e+00 | 2.1e-04 9.2e-07 6.5e-04 7600 2.6e-01 | 8.0e+02 8.0e+02 | 6.9e-01 1.4e-04 1.0e+00 | 2.1e-04 8.7e-07 6.4e-04 7800 2.7e-01 | 8.0e+02 8.0e+02 | 6.9e-01 1.3e-04 1.0e+00 | 2.1e-04 8.1e-07 6.4e-04 8000 2.8e-01 | 8.0e+02 8.0e+02 | 6.8e-01 1.3e-04 9.6e-01 | 2.0e-04 7.9e-07 6.0e-04 8200 2.8e-01 | 8.0e+02 8.0e+02 | 6.7e-01 1.1e-04 9.4e-01 | 2.0e-04 7.0e-07 5.9e-04 8400 2.9e-01 | 8.0e+02 8.0e+02 | 6.7e-01 1.1e-04 1.0e+00 | 2.0e-04 6.6e-07 6.4e-04 8600 3.0e-01 | 8.0e+02 8.0e+02 | 6.5e-01 1.0e-04 8.8e-01 | 1.9e-04 6.4e-07 5.5e-04 8800 3.0e-01 | 8.0e+02 8.0e+02 | 6.3e-01 9.5e-05 8.0e-01 | 1.9e-04 5.9e-07 5.0e-04 9000 3.1e-01 | 8.0e+02 8.0e+02 | 6.3e-01 9.3e-05 8.4e-01 | 1.9e-04 5.8e-07 5.3e-04 9200 3.2e-01 | 8.0e+02 8.0e+02 | 6.3e-01 8.7e-05 9.3e-01 | 1.9e-04 5.4e-07 5.8e-04 9400 3.2e-01 | 8.0e+02 8.0e+02 | 6.3e-01 7.0e-05 9.9e-01 | 1.9e-04 4.4e-07 6.2e-04 9600 3.3e-01 | 8.0e+02 8.0e+02 | 6.2e-01 7.0e-05 9.5e-01 | 1.9e-04 4.3e-07 6.0e-04 9800 3.4e-01 | 8.0e+02 8.0e+02 | 6.1e-01 6.6e-05 9.3e-01 | 1.8e-04 4.1e-07 5.8e-04 10000 3.5e-01 | 8.0e+02 8.0e+02 | 6.1e-01 6.3e-05 9.1e-01 | 1.8e-04 3.9e-07 5.7e-04 11000 3.8e-01 | 8.0e+02 8.0e+02 | 5.9e-01 3.1e-05 8.9e-01 | 1.8e-04 1.9e-07 5.6e-04 12000 4.1e-01 | 8.0e+02 8.0e+02 | 5.7e-01 2.6e-05 8.6e-01 | 1.7e-04 1.6e-07 5.4e-04 13000 4.5e-01 | 8.0e+02 8.0e+02 | 5.7e-01 2.5e-05 8.6e-01 | 1.7e-04 1.5e-07 5.4e-04 14000 4.8e-01 | 8.0e+02 8.0e+02 | 5.6e-01 2.4e-05 8.3e-01 | 1.7e-04 1.5e-07 5.2e-04 15000 5.2e-01 | 8.0e+02 8.0e+02 | 5.4e-01 9.8e-05 7.9e-01 | 1.6e-04 6.1e-07 5.0e-04 16000 5.5e-01 | 8.0e+02 8.0e+02 | 4.7e-01 9.4e-05 6.2e-01 | 1.4e-04 5.8e-07 3.9e-04 17000 5.8e-01 | 8.0e+02 8.0e+02 | 3.4e-01 9.0e-05 4.8e-01 | 1.0e-04 5.6e-07 3.0e-04 18000 6.2e-01 | 8.0e+02 8.0e+02 | 3.1e-01 8.3e-05 3.7e-01 | 9.3e-05 5.1e-07 2.3e-04 19000 6.5e-01 | 8.0e+02 8.0e+02 | 3.0e-01 8.0e-05 3.4e-01 | 8.9e-05 5.0e-07 2.1e-04 20000 6.8e-01 | 8.0e+02 8.0e+02 | 2.9e-01 7.8e-05 3.1e-01 | 8.6e-05 4.8e-07 1.9e-04 21000 7.2e-01 | 8.0e+02 8.0e+02 | 2.5e-01 7.7e-05 2.3e-01 | 7.7e-05 4.8e-07 1.4e-04 --------------------------------------------------------------------------------------- Solution Summary Status : OPTIMAL Presolve time : 0.261 sec Precondition time : 0.003004 sec Solve time : 0.753 sec Iterations : 21800 Primal objective : 796.3726271 Dual objective : 796.3513969 Objective gap : 1.332e-05 Primal infeas : 6.223e-05 Dual infeas : 4.619e-07 solution_summary(; result = 1, verbose = false) ├ solver_name : CuPDLPx ├ Termination │ ├ termination_status : OPTIMAL │ ├ result_count : 1 │ └ raw_status : Solver finished ├ Solution (result = 1) │ ├ primal_status : FEASIBLE_POINT │ ├ dual_status : FEASIBLE_POINT │ ├ objective_value : 7.96373e+02 │ └ dual_objective_value : 7.96351e+02 └ Work counters └ solve_time (sec) : 7.52827e-01 TRYING TO GET DUAL VALUE 285.565411 seconds (5.06 M allocations: 268.503 MiB, 0.42% gc time, 0.82% compilation time)odow commentedon Jan 28, 2026
I don't understand. Zedong the code you've referenced is for an affine constraint. Do you support returning duals from fixed variables? (VariableIndex-in-EqualTo)?
And @dlcole3 does your example even return the correct solution?
ZedongPeng commentedon Jan 28, 2026
My bad. I didn’t notice it was the reduced cost. cuPDLPx does return the reduced cost in the result, but the current MOI_wrapper doesn’t support it yet.
Would that explain why it’s so slow right now?
CuPDLPx.jl/test/MOI_wrapper.jl
Lines 33 to 56 in bc521d6
odow commentedon Jan 28, 2026
I assume it's probably computing via the fallback, which queries each row, forms the transpose of the matrix, etc.
odow commentedon Jan 28, 2026
I strongly encourage you to fix any tests which are currently skipped. The tests are there for a reason 😄
ZedongPeng commentedon Jan 28, 2026
Thank you, @odow. I will fix it.
Sorry @dlcole3 . You might need to wait until I fix it.
odow commentedon Jan 28, 2026
You just need to implement this method:
blegat commentedon Jan 29, 2026
Indeed, it looks like this is going through: https://github.com/jump-dev/MathOptInterface.jl/blob/6c45e7b9f76426b690262d5880c6f3aae62062ba/src/Utilities/results.jl#L440-L449
which will be quite slow, you can confirm this using
@profview. @odow 's suggestion should fix it.ZedongPeng commentedon Jan 30, 2026
Hi @dlcole3 . The reduced cost is now supported. You will need to install
CuPDLPx.jlfrom source at this moment.dlcole3 commentedon Feb 2, 2026
@ZedongPeng I have updated to use the main branch with the recent PR, and it is working great now. Thank you so much for your quick response in getting this working!