Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions .github/workflows/main-arm64.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
name: Build cuOpt link for GAMS (ARM64)

on:
push:
# branches: [main]
tags:
- '*'
pull_request:
workflow_dispatch:

jobs:
build-link:
runs-on: ubuntu-24.04-arm
container:
image: python:3.12

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Install dependencies
run: |
apt-get update && apt-get install -y patchelf curl unzip zip gcc

# Get CUDA runtimes via pip
- name: Set up python virtual environments with NVIDIA dependencies for CUDA 12 and CUDA 13 (respectively)
run: |
mkdir -p venvs
python -m venv venvs/cu12
bash -c "source venvs/cu12/bin/activate && \
pip install --upgrade pip -qq && \
pip install --extra-index-url=https://pypi.nvidia.com cuopt-cu12==25.12.* -qq &&
deactivate"
python -m venv venvs/cu13
bash -c "source venvs/cu13/bin/activate && \
pip install --upgrade pip -qq && \
pip install --extra-index-url=https://pypi.nvidia.com cuopt-cu13==25.12.* -qq &&
deactivate"

# Get GAMS (ARM64 version)
- name: Download and extract latest GAMS distribution
run: |
curl https://d37drm4t2jghv5.cloudfront.net/distributions/latest/linux/linux_arm64_sfx.exe --output linux_arm64_sfx.exe
unzip -q linux_arm64_sfx.exe
mv gams*_linux_arm64_sfx gamsdist
rm linux_arm64_sfx.exe

# Build link
- name: Compile GAMS/cuOpt-link binary "gmscuopt.out" for CUDA 12 and then for CUDA 13
run: |
export GAMSCAPI="gamsdist/apifiles/C/api"
export CUOPT="venvs/cu12/lib/python3.12/site-packages/libcuopt"
export JITLINK="venvs/cu12/lib/python3.12/site-packages/nvidia/nvjitlink/lib"
export CUOPT_VERSION="`cat "$CUOPT/VERSION"`"
export CUOPT_HASH="`cat "$CUOPT/GIT_COMMIT"`"
gcc -Wall gmscuopt.c -o gmscuopt-cu12.out \
-DCUOPT_VERSION=\"$CUOPT_VERSION\" -DCUOPT_HASH=\"$CUOPT_HASH\" \
-I $GAMSCAPI $GAMSCAPI/gmomcc.c $GAMSCAPI/optcc.c $GAMSCAPI/gevmcc.c \
-I $CUOPT/include $JITLINK/libnvJitLink.so.12 -L $CUOPT/lib64 -lcuopt
patchelf --set-rpath \$ORIGIN gmscuopt-cu12.out
export CUOPT="venvs/cu13/lib/python3.12/site-packages/libcuopt"
export JITLINK="venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib"
export CUOPT_VERSION="`cat "$CUOPT/VERSION"`"
export CUOPT_HASH="`cat "$CUOPT/GIT_COMMIT"`"
gcc -Wall gmscuopt.c -o gmscuopt-cu13.out \
-DCUOPT_VERSION=\"$CUOPT_VERSION\" -DCUOPT_HASH=\"$CUOPT_HASH\" \
-I $GAMSCAPI $GAMSCAPI/gmomcc.c $GAMSCAPI/optcc.c $GAMSCAPI/gevmcc.c \
-I $CUOPT/include $JITLINK/libnvJitLink.so.13 -L $CUOPT/lib64 -lcuopt
patchelf --set-rpath \$ORIGIN gmscuopt-cu13.out

# Collect dependencies for link and runtime convenience archive
- name: Prepare release artifact and runtime bundle
run: |
mkdir release-cu12
cp gmscuopt-cu12.out release-cu12/gmscuopt.out
cp assets/* release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/libcuopt/lib64/libcuopt.so release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/libcuopt/lib64/libmps_parser.so release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libgomp-*.so.1.0.0 release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libtbb-*.so.2 release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libtbbmalloc-*.so.2 release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/rapids_logger/lib64/librapids_logger.so release-cu12/
cp venvs/cu12/lib/python3.12/site-packages/librmm/lib64/librmm.so release-cu12/
mkdir runtime-cu12
cp venvs/cu12/lib/python3.12/site-packages/nvidia/cu12/lib/libcudss.so.0 runtime-cu12/
cp venvs/cu12/lib/python3.12/site-packages/nvidia/cu12/lib/libcudss_mtlayer_gomp.so.0 runtime-cu12/
cp venvs/cu12/lib/python3.12/site-packages/nvidia/cusolver/lib/libcusolver.so.11 runtime-cu12/
cp venvs/cu12/lib/python3.12/site-packages/nvidia/cublas/lib/libcublas.so.12 runtime-cu12/
cp venvs/cu12/lib/python3.12/site-packages/nvidia/cublas/lib/libcublasLt.so.12 runtime-cu12/
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/
mkdir release-cu13
cp gmscuopt-cu13.out release-cu13/gmscuopt.out
cp assets/* release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/libcuopt/lib64/libcuopt.so release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/libcuopt/lib64/libmps_parser.so release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libgomp-*.so.1.0.0 release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libtbb-*.so.2 release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libtbbmalloc-*.so.2 release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/rapids_logger/lib64/librapids_logger.so release-cu13/
cp venvs/cu13/lib/python3.12/site-packages/librmm/lib64/librmm.so release-cu13/
mkdir runtime-cu13
cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcudss.so.0 runtime-cu13/
cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcudss_mtlayer_gomp.so.0 runtime-cu13/
cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libnvJitLink.so.13 runtime-cu13/
cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcublas.so.13 runtime-cu13/
cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcublasLt.so.13 runtime-cu13/
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/

# Upload artifacts
- name: Upload CUDA 12 link artifact to GitHub Actions (always)
uses: actions/upload-artifact@v4
with:
name: cuopt-link-cu12-arm64
path: release-cu12/

- name: Upload CUDA 12 runtime artifact to GitHub Actions (always)
uses: actions/upload-artifact@v4
with:
name: cu12-runtime-arm64
path: runtime-cu12/

- name: Upload CUDA 13 link artifact to GitHub Actions (always)
uses: actions/upload-artifact@v4
with:
name: cuopt-link-cu13-arm64
path: release-cu13/

- name: Upload CUDA 13 runtime artifact to GitHub Actions (always)
uses: actions/upload-artifact@v4
with:
name: cu13-runtime-arm64
path: runtime-cu13/

# Zip Files
- name: Create zip archive (only on tag push)
if: startsWith(github.ref, 'refs/tags/')
run: |
cd release-cu12
zip -r ../cuopt-link-release-cu12-arm64.zip .
cd ../runtime-cu12
zip -r ../cu12-runtime-arm64.zip .
cd ../release-cu13
zip -r ../cuopt-link-release-cu13-arm64.zip .
cd ../runtime-cu13
zip -r ../cu13-runtime-arm64.zip .

# Create new release with archives
- name: Create GitHub Release (only on tag push)
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: |
cuopt-link-release-cu12-arm64.zip
cu12-runtime-arm64.zip
cuopt-link-release-cu13-arm64.zip
cu13-runtime-arm64.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 changes: 12 additions & 11 deletions .github/workflows/main.yml → .github/workflows/main-x86_64.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
name: Build cuOpt link for GAMS
name: Build cuOpt link for GAMS (x86_64)

on:
push:
# branches: [main]
tags:
- '*' # Run only when a new tag is pushed
pull_request:
workflow_dispatch:

jobs:
build-link:
Expand All @@ -28,12 +29,12 @@ jobs:
python -m venv venvs/cu12
bash -c "source venvs/cu12/bin/activate && \
pip install --upgrade pip -qq && \
pip install --extra-index-url=https://pypi.nvidia.com cuopt-cu12==25.10.* cuda-toolkit[cudart,nvjitlink]==12.9.* -qq &&
pip install --extra-index-url=https://pypi.nvidia.com cuopt-cu12==25.12.* -qq &&
deactivate"
python -m venv venvs/cu13
bash -c "source venvs/cu13/bin/activate && \
pip install --upgrade pip -qq && \
pip install --extra-index-url=https://pypi.nvidia.com cuopt-cu13==25.10.* cuda-toolkit[cudart,nvjitlink]==13.0.* -qq &&
pip install --extra-index-url=https://pypi.nvidia.com cuopt-cu13==25.12.* -qq &&
deactivate"

# Get GAMS
Expand Down Expand Up @@ -139,23 +140,23 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
run: |
cd release-cu12
zip -r ../cuopt-link-release-cu12.zip .
zip -r ../cuopt-link-release-cu12-x86_64.zip .
cd ../runtime-cu12
zip -r ../cu12-runtime.zip .
zip -r ../cu12-runtime-x86_64.zip .
cd ../release-cu13
zip -r ../cuopt-link-release-cu13.zip .
zip -r ../cuopt-link-release-cu13-x86_64.zip .
cd ../runtime-cu13
zip -r ../cu13-runtime.zip .
zip -r ../cu13-runtime-x86_64.zip .

# Create new release with archives
- name: Create GitHub Release (only on tag push)
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
with:
files: |
cuopt-link-release-cu12.zip
cu12-runtime.zip
cuopt-link-release-cu13.zip
cu13-runtime.zip
cuopt-link-release-cu12-x86_64.zip
cu12-runtime-x86_64.zip
cuopt-link-release-cu13-x86_64.zip
cu13-runtime-x86_64.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ You can get more details and tips by reading the blog post ["GPU-Accelerated Opt
## Requirements

- **Operating System:** Linux, Windows 11 through WSL2
- **CPU architecture:** x86_64, arm64
- **GAMS:** Version 49 or newer
- **GAMSPy:** Version 1.12.1 or newer
- **NVIDIA GPU:** Volta architecture or better
Expand All @@ -17,11 +18,11 @@ You can get more details and tips by reading the blog post ["GPU-Accelerated Opt
## Getting started / installation

- Make sure [CUDA runtime](https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64) is installed
- Download and unpack `cuopt-link-release-cu12.zip` or `cuopt-link-release-cu13.zip` (for CUDA 12 and 13 respectively) from the [releases page](https://github.com/GAMS-dev/cuoptlink-builder/releases):
- Unpack the contents of `cuopt-link-release-cu*.zip` into your GAMS system directory. For GAMSPy, you can find out your system directory by running `gamspy show base`. So for example you can run `unzip -o cuopt-link-release-cu*.zip -d $(gamspy show base)`.
- Download and unpack `cuopt-link-release-cu12.zip` or `cuopt-link-release-cu13-{x86_64,arm64}.zip` (for CUDA 12 and 13 respectively) from the [releases page](https://github.com/GAMS-dev/cuoptlink-builder/releases):
- Unpack the contents of `cuopt-link-release-cu*-{x86_64,arm64}.zip` into your GAMS system directory. For GAMSPy, you can find out your system directory by running `gamspy show base`. So for example you can run `unzip -o cuopt-link-release-cu*.zip -d $(gamspy show base)`.
- **Caution:** This will overwrite any existing `gamsconfig.yaml` file in that directory. The contained `gamsconfig.yaml` contains a `solverConfig` section to make cuOpt available to GAMS.

The neccessary files from the CUDA 12 or 13 runtime can also be downloaded as convenient archive `cu12-runtime.zip` or `cu13-runtime.zip` from the [releases page](https://github.com/GAMS-dev/cuoptlink-builder/releases).
The neccessary files from the CUDA 12 or 13 runtime can also be downloaded as convenient archive `cu12-runtime-{x86_64,arm64}.zip` or `cu13-runtime-{x86_64,arm64}.zip` from the [releases page](https://github.com/GAMS-dev/cuoptlink-builder/releases).

## Test the setup

Expand All @@ -33,5 +34,5 @@ gams trnsport lp cuopt

## Examples

- [examples/trnsport_cuopt.ipynb](examples/trnsport_cuopt.ipynb) for CUDA 12
- [examples/trnsport_cuopt.ipynb](examples/trnsport_cuopt_cu13.ipynb) for CUDA 13
- [examples/trnsport_cuopt.ipynb](examples/trnsport_cuopt.ipynb) for CUDA 12 on x86_64
- [examples/trnsport_cuopt.ipynb](examples/trnsport_cuopt_cu13.ipynb) for CUDA 13 on x86_64
2 changes: 2 additions & 0 deletions assets/optcuopt.def
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* optcuopt.def
*
num_cpu_threads integer 0 -1 -1 maxint 1 1 Controls the number of CPU threads used in the LP and MIP solvers (default GAMS Threads)
num_gpus integer 0 1 1 2 1 2 Controls the number of GPUs to use for the solve. This setting is only relevant for LP problems that uses concurrent mode and supports up to 2 GPUs at the moment. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources.
presolve boolean 0 0 1 1 Controls whether presolve is enabled. Presolve can reduce problem size and improve solve time. Enabled by default for MIP, disabled by default for LP.
dual_postsolve boolean 0 0 1 2 Controls whether dual postsolve is enabled. Disabling dual postsolve can improve solve time at the expense of not having access to the dual solution. Enabled by default for LP when presolve is enabled. This is not relevant for MIP problems
time_limit integer 0 maxint 0 maxint 1 1 Controls the time limit in seconds after which the solver will stop and return the current solution (default GAMS ResLim)
Expand Down Expand Up @@ -54,6 +55,7 @@ absolute_gap_tolerance double 0 0.0001 0 maxdouble 1 2 Controls the absolute gap
relative_gap_tolerance double 0 0.0001 0 maxdouble 1 2 Controls the relative gap tolerance used in PDLP's duality gap check
primal_infeasible_tolerance double 0 1e-08 0 maxdouble 0 2 Unknown
dual_infeasible_tolerance double 0 1e-08 0 maxdouble 0 2 Unknown
miptrace string 0 "" 1 1 filename of MIP trace file
mip_heuristics_only boolean 0 0 1 3 Controls if only the GPU heuristics should be run
mip_scaling boolean 0 1 1 3 Controls if scaling should be applied to the MIP problem
mip_absolute_tolerance double 0 0.0001 0 maxdouble 1 3 Controls the MIP absolute tolerance
Expand Down
4 changes: 2 additions & 2 deletions examples/trnsport_cuopt.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
"import sys\n",
"!pip install -q gamspy\n",
"gams_base_path = subprocess.check_output([sys.executable, '-m', 'gamspy', 'show', 'base']).decode('utf-8').strip()\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cu12-runtime.zip\"\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cuopt-link-release-cu12.zip\"\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cu12-runtime-x86_64.zip\"\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cuopt-link-release-cu12-x86_64.zip\"\n",
"subprocess.run(f\"unzip -q -o cu12-runtime.zip -d {gams_base_path}\", shell=True, check=True)\n",
"subprocess.run(f\"unzip -q -o cuopt-link-release-cu12.zip -d {gams_base_path}\", shell=True, check=True)"
]
Expand Down
4 changes: 2 additions & 2 deletions examples/trnsport_cuopt_cu13.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"import sys\n",
"!pip install -q gamspy\n",
"gams_base_path = subprocess.check_output([sys.executable, '-m', 'gamspy', 'show', 'base']).decode('utf-8').strip()\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cu13-runtime.zip\"\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cuopt-link-release-cu13.zip\"\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cu13-runtime-x86_64.zip\"\n",
"!wget -nc -nv --show-progress -q \"https://github.com/GAMS-dev/cuoptlink-builder/releases/latest/download/cuopt-link-release-cu13-x86_64.zip\"\n",
"subprocess.run(f\"unzip -q -o cu13-runtime.zip -d {gams_base_path}\", shell=True, check=True)\n",
"subprocess.run(f\"unzip -q -o cuopt-link-release-cu13.zip -d {gams_base_path}\", shell=True, check=True)"
]
Expand Down
Loading