diff --git a/.github/workflows/main-arm64.yml b/.github/workflows/main-arm64.yml index 9b4810f..1db0f9c 100644 --- a/.github/workflows/main-arm64.yml +++ b/.github/workflows/main-arm64.yml @@ -4,7 +4,7 @@ on: push: # branches: [main] tags: - - '*' + - '*' # Run only when a new tag is pushed pull_request: workflow_dispatch: @@ -29,12 +29,12 @@ jobs: python -m venv venvs/cu12 bash -c "source venvs/cu12/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu12==26.2.* -qq && + pip install --timeout=150 --pre --extra-index-url=https://pypi.nvidia.com --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/ cuopt-cu12==26.4.0a172 -qq && deactivate" python -m venv venvs/cu13 bash -c "source venvs/cu13/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu13==26.2.* -qq && + pip install --timeout=150 --pre --extra-index-url=https://pypi.nvidia.com --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/ cuopt-cu13==26.4.0a172 -qq && deactivate" # Get GAMS (ARM64 version) @@ -90,6 +90,9 @@ jobs: cp venvs/cu12/lib/python3.12/site-packages/nvidia/nvjitlink/lib/libnvJitLink.so.12 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/curand/lib/libcurand.so.10 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/cusparse/lib/libcusparse.so.12 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libssl-1d7de573.so.1.1.1k runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcares-cd559487.so.2.2.0 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcrypto-f167a748.so.1.1.1k runtime-cu12/ mkdir release-cu13 cp gmscuopt-cu13.out release-cu13/gmscuopt.out cp assets/* release-cu13/ @@ -109,6 +112,9 @@ jobs: cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcurand.so.10 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusolver.so.12 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusparse.so.12 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libssl-1d7de573.so.1.1.1k runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcares-cd559487.so.2.2.0 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcrypto-f167a748.so.1.1.1k runtime-cu13/ # Upload artifacts - name: Upload CUDA 12 link artifact to GitHub Actions (always) diff --git a/.github/workflows/main-x86_64.yml b/.github/workflows/main-x86_64.yml index c2e625d..c86b870 100644 --- a/.github/workflows/main-x86_64.yml +++ b/.github/workflows/main-x86_64.yml @@ -22,6 +22,14 @@ jobs: run: | apt-get update && apt-get install -y patchelf curl unzip zip gcc + # Download custom cuOpt wheel artifact + #- name: Download and extract cuopt-int64 wheel + # run: | + # curl -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + # https://api.github.com/repos/GAMS-dev/cuopt-int64/actions/artifacts/5869680145/zip \ + # --output cuopt-int64-wheel.zip + # unzip -q cuopt-int64-wheel.zip -d cuopt_wheel_dir + # Get CUDA runtimes via pip - name: Set up python virtual environments with NVIDIA dependencies for CUDA 12 and CUDA 13 (respectively) run: | @@ -29,13 +37,13 @@ jobs: python -m venv venvs/cu12 bash -c "source venvs/cu12/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu12==26.2.* -qq && + pip install --timeout=150 --pre --extra-index-url=https://pypi.nvidia.com --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/ cuopt-cu12==26.4.0a172 && deactivate" python -m venv venvs/cu13 bash -c "source venvs/cu13/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu13==26.2.* -qq && - deactivate" + pip install --timeout=150 --pre --extra-index-url=https://pypi.nvidia.com --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/ cuopt-cu13==26.4.0a172 && deactivate" +# pip install --force-reinstall --no-deps cuopt_wheel_dir/*.whl --extra-index-url https://pypi.anaconda.org/rapidsai-wheels-nightly/simple/ --pre && deactivate" # Get GAMS - name: Download and extract latest GAMS distribution @@ -90,6 +98,9 @@ jobs: cp venvs/cu12/lib/python3.12/site-packages/nvidia/nvjitlink/lib/libnvJitLink.so.12 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/curand/lib/libcurand.so.10 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/cusparse/lib/libcusparse.so.12 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libssl-1d7de573.so.1.1.1k runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcares-cd559487.so.2.2.0 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcrypto-f167a748.so.1.1.1k runtime-cu12/ mkdir release-cu13 cp gmscuopt-cu13.out release-cu13/gmscuopt.out cp assets/* release-cu13/ @@ -109,6 +120,9 @@ jobs: cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcurand.so.10 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusolver.so.12 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusparse.so.12 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libssl-1d7de573.so.1.1.1k runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcares-cd559487.so.2.2.0 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcrypto-f167a748.so.1.1.1k runtime-cu13/ # Upload artifacts - name: Upload CUDA 12 link artifact to GitHub Actions (always) diff --git a/assets/optcuopt.def b/assets/optcuopt.def index b81a692..f2eb588 100644 --- a/assets/optcuopt.def +++ b/assets/optcuopt.def @@ -22,6 +22,11 @@ method enumint 0 0 1 2 Controls the method to solve the linear programming probl 1 1 pdlp Use the PDLP method. 2 1 dual_simplex Use the dual simplex method. 3 1 method_barrier Use the barrier (interior-point) method. + pdlp_precision enumint 0 -1 1 2 PDLP precision mode constants + -1 1 default By default, PDLP operates in the native precision of the problem type (FP64 for double-precision problems). + 0 1 single Run PDLP internally in FP32, with automatic conversion of inputs and outputs. FP32 uses half the memory and allows PDHG iterations to be on average twice as fast, but may require more iterations to converge. Compatible with crossover (solution is converted back to FP64 before crossover) and concurrent mode (PDLP runs in FP32 while other solvers run in FP64). + 1 1 double Explicitly run in FP64 (same as default for double-precision problems). + 2 1 mixed Use mixed precision SpMV during PDHG iterations. The constraint matrix is stored in FP32 while vectors and compute type remain in FP64, improving SpMV performance with limited impact on convergence. Convergence checking and restart logic always use the full FP64 matrix. iteration_limit integer 0 maxint 0 maxint 1 2 Controls the iteration limit after which the solver will stop and return the current solution (default GAMS IterLim) infeasibility_detection boolean 0 0 1 2 Controls whether PDLP should detect infeasibility strict_infeasibility boolean 0 0 1 2 Controls the strict infeasibility mode in PDLP diff --git a/gmscuopt.c b/gmscuopt.c index 3be82bc..86258a2 100644 --- a/gmscuopt.c +++ b/gmscuopt.c @@ -134,6 +134,7 @@ int main(int argc, char *argv[]) cuopt_int_t num_variables = gmoN(gmo); cuopt_int_t num_constraints = gmoM(gmo); cuopt_int_t nnz = gmoNZ(gmo); + //int64_t nnz = gmoNZ64(gmo); cuopt_int_t* constraint_matrix_row_offsets=NULL; cuopt_int_t* constraint_matrix_column_indices=NULL; @@ -511,38 +512,39 @@ int main(int argc, char *argv[]) gmoModelStatSet(gmo, gmoModelStat_NoSolutionReturned); if (!optGetDefinedStr(opt, "prob_read")) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: + case CUOPT_TERMINATION_STATUS_OPTIMAL: gmoModelStatSet(gmo, gmoModelStat_OptimalGlobal); break; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: + case CUOPT_TERMINATION_STATUS_INFEASIBLE: gmoModelStatSet(gmo, gmoModelStat_InfeasibleGlobal); break; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: + case CUOPT_TERMINATION_STATUS_UNBOUNDED: gmoModelStatSet(gmo, gmoModelStat_Unbounded); break; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: gmoSolveStatSet(gmo, gmoSolveStat_Iteration); break; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: gmoSolveStatSet(gmo, gmoSolveStat_Resource); break; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: gmoSolveStatSet(gmo, gmoSolveStat_SolverErr); break; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: if (gmoModelType(gmo) == gmoProc_mip && has_integer_vars) { gmoModelStatSet(gmo, gmoModelStat_Integer); } else { gmoModelStatSet(gmo, gmoModelStat_Feasible); } break; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: if (gmoModelType(gmo) == gmoProc_mip && has_integer_vars) { gmoModelStatSet(gmo, gmoModelStat_Integer); } else { gmoModelStatSet(gmo, gmoModelStat_Feasible); } break; + case CUOPT_TERMINATION_STATUS_UNBOUNDED_OR_INFEASIBLE: default: gmoSolveStatSet(gmo, gmoSolveStat_Solver); } @@ -751,21 +753,21 @@ t program for cuOpt linear programming solver const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; default: return "Unknown";