diff --git a/.cirun.yml b/.cirun.yml new file mode 100644 index 0000000..263d0fa --- /dev/null +++ b/.cirun.yml @@ -0,0 +1,11 @@ +runners: + - name: aws-gpu-runner + cloud: aws + instance_type: g4dn.xlarge + machine_image: ami-067a4ba2816407ee9 + region: eu-north-1 + preemptible: + - true + - false + labels: + - cirun-aws-gpu diff --git a/.github/workflows/test-gpu.yaml b/.github/workflows/test-gpu.yaml new file mode 100644 index 0000000..a7d7b3c --- /dev/null +++ b/.github/workflows/test-gpu.yaml @@ -0,0 +1,65 @@ +name: GPU-CI + +on: + push: + branches: [main] + pull_request: + types: + - labeled + - opened + - synchronize + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + check: + name: "Triage: Check if GPU tests are allowed to run" + if: (!contains(github.event.pull_request.labels.*.name, 'skip-gpu-ci')) + runs-on: ubuntu-latest + steps: + - uses: flying-sheep/check@v1 + with: + success: ${{ github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'run-gpu-ci') }} + test: + name: GPU Tests + needs: check + runs-on: "cirun-aws-gpu--${{ github.run_id }}" + timeout-minutes: 30 + + defaults: + run: + shell: bash -el {0} + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Nvidia SMI sanity check + run: nvidia-smi + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + cache-dependency-glob: pyproject.toml + + - name: Install fknni + run: uv pip install --system -e ".[test]" + - name: Pip list + run: pip list + + - name: Run test + run: pytest -m gpu + + - name: Remove 'run-gpu-ci' Label + if: always() + uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: "run-gpu-ci" + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ea56d64..eda403b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -31,7 +31,7 @@ jobs: filter: blob:none fetch-depth: 0 - name: Install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v7 - name: Get test environments id: get-envs run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc9110..885e723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning][]. [keep a changelog]: https://keepachangelog.com/en/1.0.0/ [semantic versioning]: https://semver.org/spec/v2.0.0.html +## [1.3.0] + +- Add GPU CI ([#15](https://github.com/zethson/fknni/pull/15)) @zethson +- Add support for 3D imputation ([#14](https://github.com/zethson/fknni/pull/14)) @zethson +- Require Python 3.12+ ([#13](https://github.com/zethson/fknni/pull/14)) @zethson + ## [1.2.0] - Iterative imputation for very sparse datasets diff --git a/README.md b/README.md index 0804041..3ebf244 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Please refer to the [documentation][link-docs]. In particular, the ## Installation -You need to have Python 3.10 or newer installed on your system. +You need to have Python 3.12 or newer installed on your system. If you don't have Python installed, we recommend installing [Mambaforge](https://github.com/conda-forge/miniforge#mambaforge). Install the latest release of `fknni` from [PyPI](https://pypi.org/project/fknni): diff --git a/ci/environment.yml b/ci/environment.yml new file mode 100644 index 0000000..38e8c1d --- /dev/null +++ b/ci/environment.yml @@ -0,0 +1,10 @@ +name: fknni +channels: + - rapidsai + - nvidia + - conda-forge +dependencies: + - rapids=25.10 + - python=3.13 + - cuda-version=12.9 + - cudnn diff --git a/pyproject.toml b/pyproject.toml index e45f9b4..419a0b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,11 +45,24 @@ optional-dependencies.doc = [ "sphinxcontrib-bibtex>=1", "sphinxext-opengraph", ] +optional-dependencies.rapids12 = [ + "cudf-cu12>=25.10", + "cugraph-cu12>=25.10", + "cuml-cu12>=25.10", + "cupy-cuda12x", + "cuvs-cu12>=25.10", +] +optional-dependencies.rapids13 = [ + "cudf-cu13>=25.10", + "cugraph-cu13>=25.10", + "cuml-cu13>=25.10", + "cupy-cuda13x", + "cuvs-cu13>=25.10", +] optional-dependencies.test = [ "coverage", "pytest", ] - urls.Documentation = "https://fknni.readthedocs.io/" urls.Homepage = "https://github.com/zethson/fknni" urls.Source = "https://github.com/zethson/fknni" @@ -130,6 +143,9 @@ xfail_strict = true addopts = [ "--import-mode=importlib", # allow using test files with same name ] +markers = [ + "gpu: mark test to run on GPU", +] [tool.coverage.run] source = [ "fknni" ] diff --git a/tests/conftest.py b/tests/cpu/conftest.py similarity index 100% rename from tests/conftest.py rename to tests/cpu/conftest.py diff --git a/tests/test_faiss_imputation.py b/tests/cpu/test_faiss_imputation.py similarity index 100% rename from tests/test_faiss_imputation.py rename to tests/cpu/test_faiss_imputation.py diff --git a/tests/gpu/test_gpu.py b/tests/gpu/test_gpu.py new file mode 100644 index 0000000..f3891cc --- /dev/null +++ b/tests/gpu/test_gpu.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest.mark.gpu +def test_gpu(): + assert 1 + 1 == 2