diff --git a/.github/workflows/main-arm64.yml b/.github/workflows/main-arm64.yml index 4673fea..ffbd339 100644 --- a/.github/workflows/main-arm64.yml +++ b/.github/workflows/main-arm64.yml @@ -28,9 +28,9 @@ jobs: run: | mkdir -p venvs uv venv venvs/cu12 - uv pip install --python venvs/cu12 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-cu12==26.10.0a224.post261002130525' -qq + uv pip install --python venvs/cu12 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-mathopt-cu12==26.10.*' 'libcuopt-client==26.10.*' -qq uv venv venvs/cu13 - uv pip install --python venvs/cu13 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-cu13==26.10.0a224.post261002130525' -qq + uv pip install --python venvs/cu13 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-mathopt-cu13==26.10.*' 'libcuopt-client==26.10.*' -qq # Get GAMS (ARM64 version) - name: Download and extract latest GAMS distribution @@ -44,23 +44,25 @@ jobs: - 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.13/site-packages/libcuopt" + export CUOPT="venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt" export JITLINK="venvs/cu12/lib/python3.13/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_mathopt + -I $CUOPT/include -I venvs/cu12/lib/python3.13/site-packages/libcuopt_client/include $JITLINK/libnvJitLink.so.12 -L $CUOPT/lib64 -lcuopt_mathopt \ + -L venvs/cu12/lib/python3.13/site-packages/libcuopt_client/lib64 -lcuopt_client patchelf --set-rpath \$ORIGIN gmscuopt-cu12.out - export CUOPT="venvs/cu13/lib/python3.13/site-packages/libcuopt" + export CUOPT="venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt" export JITLINK="venvs/cu13/lib/python3.13/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_mathopt + -I $CUOPT/include -I venvs/cu13/lib/python3.13/site-packages/libcuopt_client/include $JITLINK/libnvJitLink.so.13 -L $CUOPT/lib64 -lcuopt_mathopt \ + -L venvs/cu13/lib/python3.13/site-packages/libcuopt_client/lib64 -lcuopt_client patchelf --set-rpath \$ORIGIN gmscuopt-cu13.out # Collect dependencies for link and runtime convenience archive @@ -69,13 +71,14 @@ jobs: mkdir release-cu12 cp gmscuopt-cu12.out release-cu12/gmscuopt.out cp assets/* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_mathopt.so release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_client.so release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libgomp-*.so* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libtbb-*.so* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libtbbmalloc-*.so* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt/lib64/libcudss_mtlayer_cuopt.so release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libcudart-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcuopt_mathopt.so release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_client/lib64/libcuopt_client.so release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libgomp-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_client.libs/libgomp-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libtbb-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libtbbmalloc-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcudss_mtlayer_cuopt.so release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libcudart-*.so* release-cu12/ cp venvs/cu12/lib/python3.13/site-packages/rapids_logger/lib64/librapids_logger.so release-cu12/ cp venvs/cu12/lib/python3.13/site-packages/librmm/lib64/librmm.so release-cu12/ cp venvs/cu12/lib/python3.13/site-packages/nvidia/nccl/lib/libnccl.so* release-cu12/ @@ -87,17 +90,18 @@ jobs: cp venvs/cu12/lib/python3.13/site-packages/nvidia/nvjitlink/lib/libnvJitLink.so* runtime-cu12/ cp venvs/cu12/lib/python3.13/site-packages/nvidia/curand/lib/libcurand.so* runtime-cu12/ cp venvs/cu12/lib/python3.13/site-packages/nvidia/cusparse/lib/libcusparse.so* runtime-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libcares-*.so* runtime-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_client.libs/libcares-*.so* runtime-cu12/ mkdir release-cu13 cp gmscuopt-cu13.out release-cu13/gmscuopt.out cp assets/* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_mathopt.so release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_client.so release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libgomp-*.so* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libtbb-*.so* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libtbbmalloc-*.so* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt/lib64/libcudss_mtlayer_cuopt.so release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libcudart-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcuopt_mathopt.so release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_client/lib64/libcuopt_client.so release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libgomp-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_client.libs/libgomp-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libtbb-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libtbbmalloc-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcudss_mtlayer_cuopt.so release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libcudart-*.so* release-cu13/ cp venvs/cu13/lib/python3.13/site-packages/rapids_logger/lib64/librapids_logger.so release-cu13/ cp venvs/cu13/lib/python3.13/site-packages/librmm/lib64/librmm.so release-cu13/ cp venvs/cu13/lib/python3.13/site-packages/nvidia/nccl/lib/libnccl.so* release-cu13/ @@ -109,7 +113,7 @@ jobs: cp venvs/cu13/lib/python3.13/site-packages/nvidia/cu13/lib/libcurand.so* runtime-cu13/ cp venvs/cu13/lib/python3.13/site-packages/nvidia/cu13/lib/libcusolver.so* runtime-cu13/ cp venvs/cu13/lib/python3.13/site-packages/nvidia/cu13/lib/libcusparse.so* runtime-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libcares-*.so* runtime-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_client.libs/libcares-*.so* 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 13ba24e..f900c4b 100644 --- a/.github/workflows/main-x86_64.yml +++ b/.github/workflows/main-x86_64.yml @@ -28,9 +28,9 @@ jobs: run: | mkdir -p venvs uv venv venvs/cu12 - uv pip install --python venvs/cu12 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-cu12==26.10.0a224.post261002130525' -qq + uv pip install --python venvs/cu12 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-mathopt-cu12==26.10.*' 'libcuopt-client==26.10.*' -qq uv venv venvs/cu13 - uv pip install --python venvs/cu13 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-cu13==26.10.0a224.post261002130525' -qq + uv pip install --python venvs/cu13 --prerelease=allow --index-strategy unsafe-best-match --extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple --extra-index-url=https://pypi.nvidia.com 'libcuopt-mathopt-cu13==26.10.*' 'libcuopt-client==26.10.*' -qq # Get GAMS - name: Download and extract latest GAMS distribution @@ -44,23 +44,25 @@ jobs: - 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.13/site-packages/libcuopt" + export CUOPT="venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt" export JITLINK="venvs/cu12/lib/python3.13/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_mathopt + -I $CUOPT/include -I venvs/cu12/lib/python3.13/site-packages/libcuopt_client/include $JITLINK/libnvJitLink.so.12 -L $CUOPT/lib64 -lcuopt_mathopt \ + -L venvs/cu12/lib/python3.13/site-packages/libcuopt_client/lib64 -lcuopt_client patchelf --set-rpath \$ORIGIN gmscuopt-cu12.out - export CUOPT="venvs/cu13/lib/python3.13/site-packages/libcuopt" + export CUOPT="venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt" export JITLINK="venvs/cu13/lib/python3.13/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_mathopt + -I $CUOPT/include -I venvs/cu13/lib/python3.13/site-packages/libcuopt_client/include $JITLINK/libnvJitLink.so.13 -L $CUOPT/lib64 -lcuopt_mathopt \ + -L venvs/cu13/lib/python3.13/site-packages/libcuopt_client/lib64 -lcuopt_client patchelf --set-rpath \$ORIGIN gmscuopt-cu13.out # Collect dependencies for link and runtime convenience archive @@ -69,13 +71,14 @@ jobs: mkdir release-cu12 cp gmscuopt-cu12.out release-cu12/gmscuopt.out cp assets/* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_mathopt.so release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_client.so release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libgomp-*.so* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libtbb-*.so* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libtbbmalloc-*.so* release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt/lib64/libcudss_mtlayer_cuopt.so release-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libcudart-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcuopt_mathopt.so release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_client/lib64/libcuopt_client.so release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libgomp-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_client.libs/libgomp-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libtbb-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libtbbmalloc-*.so* release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcudss_mtlayer_cuopt.so release-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_mathopt_cu12.libs/libcudart-*.so* release-cu12/ cp venvs/cu12/lib/python3.13/site-packages/rapids_logger/lib64/librapids_logger.so release-cu12/ cp venvs/cu12/lib/python3.13/site-packages/librmm/lib64/librmm.so release-cu12/ cp venvs/cu12/lib/python3.13/site-packages/nvidia/nccl/lib/libnccl.so* release-cu12/ @@ -87,17 +90,18 @@ jobs: cp venvs/cu12/lib/python3.13/site-packages/nvidia/nvjitlink/lib/libnvJitLink.so* runtime-cu12/ cp venvs/cu12/lib/python3.13/site-packages/nvidia/curand/lib/libcurand.so* runtime-cu12/ cp venvs/cu12/lib/python3.13/site-packages/nvidia/cusparse/lib/libcusparse.so* runtime-cu12/ - cp venvs/cu12/lib/python3.13/site-packages/libcuopt_cu12.libs/libcares-*.so* runtime-cu12/ + cp venvs/cu12/lib/python3.13/site-packages/libcuopt_client.libs/libcares-*.so* runtime-cu12/ mkdir release-cu13 cp gmscuopt-cu13.out release-cu13/gmscuopt.out cp assets/* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_mathopt.so release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt/lib64/libcuopt_client.so release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libgomp-*.so* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libtbb-*.so* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libtbbmalloc-*.so* release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt/lib64/libcudss_mtlayer_cuopt.so release-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libcudart-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcuopt_mathopt.so release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_client/lib64/libcuopt_client.so release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libgomp-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_client.libs/libgomp-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libtbb-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libtbbmalloc-*.so* release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt/lib64/libcudss_mtlayer_cuopt.so release-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_mathopt_cu13.libs/libcudart-*.so* release-cu13/ cp venvs/cu13/lib/python3.13/site-packages/rapids_logger/lib64/librapids_logger.so release-cu13/ cp venvs/cu13/lib/python3.13/site-packages/librmm/lib64/librmm.so release-cu13/ cp venvs/cu13/lib/python3.13/site-packages/nvidia/nccl/lib/libnccl.so* release-cu13/ @@ -109,7 +113,7 @@ jobs: cp venvs/cu13/lib/python3.13/site-packages/nvidia/cu13/lib/libcurand.so* runtime-cu13/ cp venvs/cu13/lib/python3.13/site-packages/nvidia/cu13/lib/libcusolver.so* runtime-cu13/ cp venvs/cu13/lib/python3.13/site-packages/nvidia/cu13/lib/libcusparse.so* runtime-cu13/ - cp venvs/cu13/lib/python3.13/site-packages/libcuopt_cu13.libs/libcares-*.so* runtime-cu13/ + cp venvs/cu13/lib/python3.13/site-packages/libcuopt_client.libs/libcares-*.so* runtime-cu13/ # Upload artifacts - name: Upload CUDA 12 link artifact to GitHub Actions (always) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 43e886b..2638fae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,6 +32,8 @@ New or changed cuOpt options go into `assets/optcuopt.def` and have to be passed The GPU tests use the GAMS system found in your `PATH`, with the link installed. +Without a local GPU, open `tests/colab-gpu-test.ipynb` in Google Colab with a GPU runtime: it builds the link from a branch the same way as CI, installs it into a fresh GAMS system and runs a `trnsport` smoke test and `tests/test-gamslib-cuopt.py`. + ## Pull requests - Keep each pull request focused on one change and describe how you tested it. diff --git a/README.md b/README.md index 20caf86..23e939e 100644 --- a/README.md +++ b/README.md @@ -168,3 +168,5 @@ python3 tests/test-gamslib-cuopt.py -g -j 2 # -g defau ``` Use `-r` to change the time limit per model (default 120s; an optional fourth column in `tests/baseline.txt` sets a model-specific time limit instead), `-t` for the relative tolerance (default 1e-6) and pass model names to run only a subset. The exit code is 1 if any model mismatches or fails to produce a solution. + +To run it on a Colab GPU against a branch of this repository, use [`tests/colab-gpu-test.ipynb`](tests/colab-gpu-test.ipynb). diff --git a/build-link.sh b/build-link.sh index bbdc987..c3d7ef7 100755 --- a/build-link.sh +++ b/build-link.sh @@ -6,8 +6,7 @@ set -e # Users can export these before running the script, otherwise defaults are used. GAMSDIST="${GAMSDIST:-$HOME/gamsdist}" WORKSPACE="${WORKSPACE:-$(pwd)}" -CUOPT_VERSION="${CUOPT_VERSION:-26.08}" -CUOPT_HASH="${CUOPT_HASH:-12345}" +# Read build provenance from the mathopt wheel unless explicitly overridden below. # 2. Dynamically find the site-packages directory to avoid hardcoding the Python version # or the venv directory name (some setups use "venv", others "uv"-style ".venv"). @@ -27,8 +26,10 @@ fi # 3. Export specific build paths export GAMSCAPI="$GAMSDIST/apifiles/C/api" -export CUOPT="$SITE_PACKAGES/libcuopt" +export CUOPT="$SITE_PACKAGES/libcuopt_mathopt" export JITLINK="$SITE_PACKAGES/nvidia/cu13/lib" +CUOPT_VERSION="${CUOPT_VERSION:-$(<"$CUOPT/VERSION")}" +CUOPT_HASH="${CUOPT_HASH:-$(<"$CUOPT/GIT_COMMIT")}" echo "Building GAMS cuOpt solver link..." echo "Using GAMSDIST: $GAMSDIST" @@ -39,8 +40,9 @@ gcc -g3 -O0 -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_mathopt + -I "$CUOPT/include" -I "$SITE_PACKAGES/libcuopt_client/include" "$JITLINK/libnvJitLink.so.13" \ + -L "$CUOPT/lib64" -lcuopt_mathopt \ + -L "$SITE_PACKAGES/libcuopt_client/lib64" -lcuopt_client # 5. Patch RPATH patchelf --set-rpath \$ORIGIN gmscuopt-cu13.out @@ -54,12 +56,13 @@ mkdir -p "$GAMSDIST" mv gmscuopt-cu13.out "$GAMSDIST/gmscuopt.out" cp "$CUOPT/lib64/libcuopt_mathopt.so" "$GAMSDIST/" -cp "$CUOPT/lib64/libcuopt_client.so" "$GAMSDIST/" -cp "$SITE_PACKAGES"/libcuopt_cu13.libs/libgomp-*.so* "$GAMSDIST/" -cp "$SITE_PACKAGES"/libcuopt_cu13.libs/libtbb-*.so* "$GAMSDIST/" -cp "$SITE_PACKAGES"/libcuopt_cu13.libs/libtbbmalloc-*.so* "$GAMSDIST/" -cp "$SITE_PACKAGES"/libcuopt/lib64/libcudss_mtlayer_cuopt.so "$GAMSDIST/" -cp "$SITE_PACKAGES"/libcuopt_cu13.libs/libcudart-*.so* "$GAMSDIST/" +cp "$SITE_PACKAGES/libcuopt_client/lib64/libcuopt_client.so" "$GAMSDIST/" +cp "$SITE_PACKAGES"/libcuopt_mathopt_cu13.libs/libgomp-*.so* "$GAMSDIST/" +cp "$SITE_PACKAGES"/libcuopt_client.libs/libgomp-*.so* "$GAMSDIST/" +cp "$SITE_PACKAGES"/libcuopt_mathopt_cu13.libs/libtbb-*.so* "$GAMSDIST/" +cp "$SITE_PACKAGES"/libcuopt_mathopt_cu13.libs/libtbbmalloc-*.so* "$GAMSDIST/" +cp "$CUOPT/lib64/libcudss_mtlayer_cuopt.so" "$GAMSDIST/" +cp "$SITE_PACKAGES"/libcuopt_mathopt_cu13.libs/libcudart-*.so* "$GAMSDIST/" cp "$SITE_PACKAGES"/rapids_logger/lib64/librapids_logger.so "$GAMSDIST/" cp "$SITE_PACKAGES"/librmm/lib64/librmm.so "$GAMSDIST/" cp "$SITE_PACKAGES"/nvidia/cu13/lib/libcudss.so* "$GAMSDIST/" @@ -69,7 +72,7 @@ cp "$SITE_PACKAGES"/nvidia/cu13/lib/libcublasLt.so* "$GAMSDIST/" cp "$SITE_PACKAGES"/nvidia/cu13/lib/libcurand.so* "$GAMSDIST/" cp "$SITE_PACKAGES"/nvidia/cu13/lib/libcusolver.so* "$GAMSDIST/" cp "$SITE_PACKAGES"/nvidia/cu13/lib/libcusparse.so* "$GAMSDIST/" -cp "$SITE_PACKAGES"/libcuopt_cu13.libs/libcares-*.so* "$GAMSDIST/" +cp "$SITE_PACKAGES"/libcuopt_client.libs/libcares-*.so* "$GAMSDIST/" cp "$SITE_PACKAGES"/nvidia/nccl/lib/libnccl.so* "$GAMSDIST/" # Copy assets (suppress errors if directory is empty or missing) diff --git a/tests/colab-gpu-test.ipynb b/tests/colab-gpu-test.ipynb new file mode 100644 index 0000000..f3e87d5 --- /dev/null +++ b/tests/colab-gpu-test.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# cuOpt link GPU test on Colab\n", + "\n", + "Builds the GAMS/cuOpt link from a branch of this repository exactly like the x86_64 CI workflow, installs it into a fresh GAMS distribution and runs the GPU-dependent tests: a `trnsport` smoke test and `tests/test-gamslib-cuopt.py`.\n", + "\n", + "1. **Runtime > Change runtime type > T4 GPU** (any NVIDIA GPU works).\n", + "2. Optional: store a GAMS license as Colab secret `GAMS_LICENSE` (key icon in the left sidebar, paste the content of `gamslice.txt`, enable notebook access). Without it GAMS runs in demo mode and larger gamslib models fail on size limits.\n", + "3. Set the branch below and run all cells." + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "BRANCH = \"main\" # branch of GAMS-dev/cuoptlink-builder to build and test\n", + "CUDA = None # 12 or 13; None picks the newest one the GPU driver supports\n", + "MODELS = [] # gamslib models to test, empty list runs the full baseline\n", + "RESLIM = 120 # time limit per model in seconds" + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "import os, re, shutil, subprocess, sys\n", + "\n", + "smi = subprocess.run([\"nvidia-smi\"], capture_output=True, text=True)\n", + "if smi.returncode != 0:\n", + " raise SystemExit(\"No NVIDIA GPU found: select a GPU runtime (Runtime > Change runtime type)\")\n", + "print(smi.stdout)\n", + "driver_cuda = int(re.search(r\"CUDA Version:\\s*(\\d+)\", smi.stdout).group(1))\n", + "if CUDA is None:\n", + " CUDA = 13 if driver_cuda >= 13 else 12\n", + "if CUDA > driver_cuda:\n", + " raise SystemExit(f\"Driver supports CUDA {driver_cuda}, cannot run the CUDA {CUDA} build\")\n", + "print(f\"Testing the CUDA {CUDA} build\")" + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "WORK = \"/content/cuoptlink-builder\"\n", + "shutil.rmtree(WORK, ignore_errors=True)\n", + "subprocess.run([\"git\", \"clone\", \"-q\", \"--depth\", \"1\", \"-b\", BRANCH,\n", + " \"https://github.com/GAMS-dev/cuoptlink-builder\", WORK], check=True)\n", + "subprocess.run([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"uv\", \"patchelf\", \"pyyaml\"], check=True)\n", + "print(subprocess.check_output([\"git\", \"-C\", WORK, \"log\", \"-1\", \"--format=%h %s\"], text=True))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build like CI\n", + "\n", + "Runs the `run` steps of `.github/workflows/main-x86_64.yml` (venvs, GAMS download, compile, packaging) unchanged. `UV_PYTHON=3.13` makes the venvs match the `python3.13` paths the workflow uses. Takes a few minutes." + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "import yaml\n", + "\n", + "wf = yaml.safe_load(open(f\"{WORK}/.github/workflows/main-x86_64.yml\"))\n", + "env = dict(os.environ, UV_PYTHON=\"3.13\")\n", + "for step in wf[\"jobs\"][\"build-link\"][\"steps\"]:\n", + " if \"run\" not in step or step.get(\"if\") or step[\"name\"].startswith(\"Install dependencies\"):\n", + " continue\n", + " print(\"===\", step[\"name\"], flush=True)\n", + " subprocess.run([\"bash\", \"-e\", \"-c\", step[\"run\"]], cwd=WORK, env=env, check=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Install into the GAMS distribution" + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "GAMSDIST = f\"{WORK}/gamsdist\"\n", + "for src in (f\"{WORK}/release-cu{CUDA}\", f\"{WORK}/runtime-cu{CUDA}\"):\n", + " for name in os.listdir(src):\n", + " shutil.copy2(os.path.join(src, name), GAMSDIST)\n", + "shutil.copy2(f\"{GAMSDIST}/gamsconfig_cuopt.yaml\", f\"{GAMSDIST}/gamsconfig.yaml\")\n", + "\n", + "try:\n", + " from google.colab import userdata\n", + " lic = userdata.get(\"GAMS_LICENSE\")\n", + "except Exception:\n", + " lic = None\n", + "if lic:\n", + " with open(f\"{GAMSDIST}/gamslice.txt\", \"w\") as f:\n", + " f.write(lic.strip() + \"\\n\")\n", + " print(\"GAMS license installed\")\n", + "else:\n", + " print(\"No GAMS_LICENSE secret: GAMS runs in demo mode\")\n", + "os.environ[\"PATH\"] = GAMSDIST + os.pathsep + os.environ[\"PATH\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Smoke test: trnsport" + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "smoke = \"/content/smoke\"\n", + "shutil.rmtree(smoke, ignore_errors=True)\n", + "os.makedirs(smoke)\n", + "subprocess.run([f\"{GAMSDIST}/gamslib\", \"-q\", \"trnsport\"], cwd=smoke, check=True)\n", + "# GAMS ends normally even when the solver fails, so make a non-optimal solve abort the job\n", + "with open(f\"{smoke}/trnsport.gms\", \"a\") as f:\n", + " f.write(\"\\nabort$(transport.modelStat <> %modelStat.optimal%) 'cuOpt did not solve trnsport to optimality', transport.modelStat;\\n\")\n", + "r = subprocess.run([f\"{GAMSDIST}/gams\", \"trnsport\", \"lp=cuopt\", \"lo=3\"], cwd=smoke, capture_output=True, text=True)\n", + "print(r.stdout[-4000:])\n", + "if r.returncode != 0:\n", + " raise SystemExit(f\"trnsport failed with return code {r.returncode}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## gamslib regression test\n", + "\n", + "Solves the models in `tests/baseline.txt` with cuOpt and compares the objective with the CPLEX reference." + ] + }, + { + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "r = subprocess.run([sys.executable, f\"{WORK}/tests/test-gamslib-cuopt.py\", \"-g\", GAMSDIST,\n", + " \"-r\", str(RESLIM), *MODELS], cwd=\"/content\")\n", + "print(\"PASSED\" if r.returncode == 0 else f\"FAILED (exit code {r.returncode})\")" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "gpuType": "T4", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file