Skip to content
Open
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
65 changes: 44 additions & 21 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,50 @@ concurrency:

jobs:
build:
name: Linux / CUDA ${{ matrix.cuda }}
runs-on: ubuntu-latest
container: nvidia/cuda:${{ matrix.cuda }}-devel-ubuntu22.04
name: ${{ matrix.os }} / CUDA ${{ matrix.cuda }}
runs-on: ${{ matrix.os }}
env:
CMAKE_BUILD_PARALLEL_LEVEL: "2"
strategy:
fail-fast: false
matrix:
cuda: ["12.4.0", "13.3.0"]
os: [ubuntu-22.04, windows-2022]
cuda: ["12.4.0", "12.5.0", "12.6.0", "12.8.0", "12.9.0", "13.0.0", "13.1.0"]
defaults:
run:
shell: bash

steps:
- uses: actions/checkout@v5

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- uses: ilammy/msvc-dev-cmd@v1
if: runner.os == 'Windows'
with:
arch: x64

- uses: Jimver/cuda-toolkit@v0.2.30
with:
cuda: ${{ matrix.cuda }}
linux-local-args: '["--toolkit"]'
use-github-cache: 'false'
log-file-suffix: '${{ matrix.os }}-${{ matrix.cuda }}'

- name: Install system dependencies
if: runner.os == 'Linux'
run: |
# CUDA is preinstalled in the image; these dependencies only need Ubuntu sources.
# Ignore extra repositories so NVIDIA index sync failures do not block this step.
test -s /etc/apt/sources.list
apt_options=(
-o Dir::Etc::sourcelist=/etc/apt/sources.list
-o Dir::Etc::sourceparts=-
)
apt-get "${apt_options[@]}" update
apt-get "${apt_options[@]}" install -y --no-install-recommends \
build-essential git ca-certificates python3-dev python3-venv zlib1g-dev

- uses: actions/checkout@v5
sudo apt-get update
sudo apt-get install -y --no-install-recommends zlib1g-dev

- name: Install build tools
run: |
python3 -m venv "$RUNNER_TEMP/build-env"
"$RUNNER_TEMP/build-env/bin/python" -m pip install --upgrade pip "cmake>=3.24" ninja
echo "$RUNNER_TEMP/build-env/bin" >> "$GITHUB_PATH"
python -m pip install --upgrade pip "cmake>=3.24" ninja

- name: Configure
# Check every toolkit's build; run the test suites once per OS.
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
Expand All @@ -58,18 +68,31 @@ jobs:
-DHPDLP_BUILD_SHARED_LIB=ON \
-DHPDLP_BUILD_CLI=ON \
-DHPDLP_BUILD_PYTHON=OFF \
-DHPDLP_BUILD_TESTS=ON
-DHPDLP_BUILD_TESTS=${{ matrix.cuda == '13.1.0' && 'ON' || 'OFF' }}

- name: Build
run: cmake --build build --parallel 2
run: cmake --build build

- name: Add PSLP to the Windows DLL search path
if: runner.os == 'Windows' && matrix.cuda == '13.1.0'
shell: pwsh
run: |
"$env:GITHUB_WORKSPACE\build\_deps\pslp-build" >> $env:GITHUB_PATH

- name: Run CPU tests
if: matrix.cuda == '13.1.0'
env:
LD_LIBRARY_PATH: ${{ env.CUDA_PATH }}/lib64
run: ctest --test-dir build -L cpu --output-on-failure

- name: Install Python package
if: matrix.cuda == '13.1.0'
run: |
python -m pip install ".[test]" \
--config-settings=cmake.define.CMAKE_CUDA_ARCHITECTURES=80

- name: Run Python tests
if: matrix.cuda == '13.1.0'
env:
LD_LIBRARY_PATH: ${{ env.CUDA_PATH }}/lib64
run: python -m pytest -m "not gpu"
35 changes: 24 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ project(hpdlp VERSION 0.0.1 LANGUAGES C CXX CUDA)
add_compile_definitions(HPDLP_VERSION="${PROJECT_VERSION}")

# Language standards
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -31,15 +31,6 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
"MinSizeRel" "RelWithDebInfo")
endif()

# Global compile flags
add_compile_definitions(CUSPARSE_ENABLE_EXPERIMENTAL_API)
add_compile_options(-Wall -Wextra)

# Windows compatibility
if(WIN32)
add_compile_definitions(strtok_r=strtok_s)
endif()

# -----------------------------------------------------------------------------
# CONTROL OPTIONS
# -----------------------------------------------------------------------------
Expand All @@ -51,8 +42,9 @@ option(HPDLP_BUILD_SHARED_LIB "Build the H-PDLP shared library" ON)
cmake_dependent_option(HPDLP_BUILD_PYTHON "Build the H-PDLP Python bindings" OFF
"HPDLP_BUILD_STATIC_LIB" OFF)

# The CLI uses getopt.h, libgen.h and unistd.h, which MSVC does not provide.
cmake_dependent_option(HPDLP_BUILD_CLI "Build the H-PDLP command-line executable" ON
"HPDLP_BUILD_STATIC_LIB" OFF)
"HPDLP_BUILD_STATIC_LIB;NOT MSVC" OFF)

cmake_dependent_option(HPDLP_BUILD_TESTS "Build the H-PDLP test suite" OFF
"HPDLP_BUILD_STATIC_LIB" OFF)
Expand Down Expand Up @@ -112,6 +104,25 @@ FetchContent_Declare(

FetchContent_MakeAvailable(pslp)

# Apply project flags after dependencies so they do not inherit our options.
add_compile_definitions(CUSPARSE_ENABLE_EXPERIMENTAL_API)
if(MSVC)
add_compile_options(
$<$<COMPILE_LANGUAGE:C,CXX>:/W4>
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/W4>)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS strtok_r=strtok_s)
if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA"
AND CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13)
# CUDA 13 CCCL headers require the conforming MSVC preprocessor.
# Keep CUDA 12 in its default mode.
add_compile_options($<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:preprocessor>)
endif()
else()
add_compile_options(
"$<$<COMPILE_LANGUAGE:C,CXX>:-Wall;-Wextra>"
$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:-Xcompiler=-Wall,-Wextra>)
endif()

# -----------------------------------------------------------------------------
# SOURCE DISCOVERY & TARGET DEFINITION
# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -187,6 +198,7 @@ if(HPDLP_BUILD_SHARED_LIB)
set_target_properties(
hpdlp_shared
PROPERTIES OUTPUT_NAME "hpdlp"
WINDOWS_EXPORT_ALL_SYMBOLS ON
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
CUDA_SEPARABLE_COMPILATION ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON)
Expand Down Expand Up @@ -245,6 +257,7 @@ if(NOT HPDLP_BUILD_PYTHON)
install(
TARGETS hpdlp_shared
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin) # 'bin' for DLLs on Windows, 'lib' for .so on Linux
endif()

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Maximization is supported through MPS `OBJSENSE` and the C/Python APIs. For MPS

## Installation

Linux and WSL2 are the primary build environments. Native Windows builds have not been validated.
Linux and WSL2 support all build targets. Native Windows builds with MSVC support the libraries and Python bindings; the CLI requires Linux or WSL2.

- **GPU:** an NVIDIA GPU supported by the selected CUDA toolkit.
- **CUDA Toolkit:** 12.4+ with NVCC, cuBLAS, cuSPARSE, and cuRAND.
Expand Down Expand Up @@ -116,7 +116,7 @@ cmake --build build -j
ctest --test-dir build --output-on-failure
```

See the [test guide](test/README.md) for CPU/GPU subsets and [Python tests](python/README.md#tests) for pytest instructions. CI builds everything and runs the CPU-only C tests and the non-GPU Python tests.
See the [test guide](test/README.md) for CPU/GPU subsets and [Python tests](python/README.md#tests) for pytest instructions. CI builds on Linux and Windows across the supported CUDA versions. On CUDA 13.1, both platforms also run the CPU-only C tests and the non-GPU Python tests.

## Acknowledgements

Expand Down
4 changes: 4 additions & 0 deletions test/unit/cpu/test_error_handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ static lp_problem_t *create_small_problem(void)

int main(void)
{
#ifdef _WIN32
_putenv_s("CUDA_VISIBLE_DEVICES", "-1");
#else
setenv("CUDA_VISIBLE_DEVICES", "", 1);
#endif

lp_problem_t *problem = create_small_problem();
check("problem is created without a GPU", problem != NULL);
Expand Down
8 changes: 4 additions & 4 deletions test/unit/gpu/test_active_set_masks.cu
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
#include <stdio.h>

__global__ void update_binding_constraint_mask_kernel(
const double *, const double *, const double *, const double *,
int *, bool *, active_set_mask_changes_t *, double, int, int, int);
const double *__restrict__, const double *, const double *__restrict__, const double *__restrict__,
int *__restrict__, bool *__restrict__, active_set_mask_changes_t *, double, int, int, int);
__global__ void update_free_variable_mask_kernel(
const double *, const double *, const double *, const double *,
const double *, int *, bool *, active_set_mask_changes_t *, double,
const double *__restrict__, const double *__restrict__, const double *, const double *__restrict__,
const double *__restrict__, int *__restrict__, bool *__restrict__, active_set_mask_changes_t *, double,
int, int, int);

enum { NUM_ROWS = 10, NUM_COLUMNS = 12, NUM_ZERO_SCALE_COLUMNS = 4, NUM_GAUGES = 2 };
Expand Down
Loading