Skip to content
Merged
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
37 changes: 32 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,38 @@ on:

jobs:
test:
name: ${{ matrix.label }} / py${{ matrix.python-version }}
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]
include:
# Lower bound — pinned torch 2.5.1 across all supported Python versions.
- python-version: "3.10"
label: "torch 2.5"
torch-pip-args: "torch==2.5.1+cpu torchvision==0.20.1+cpu torchaudio==2.5.1+cpu"
experimental: false
- python-version: "3.11"
label: "torch 2.5"
torch-pip-args: "torch==2.5.1+cpu torchvision==0.20.1+cpu torchaudio==2.5.1+cpu"
experimental: false
- python-version: "3.12"
label: "torch 2.5"
torch-pip-args: "torch==2.5.1+cpu torchvision==0.20.1+cpu torchaudio==2.5.1+cpu"
experimental: false
# Verified — torch 2.8 was validated end-to-end in the mosaic DDP path
# (1000-epoch run, UMAP and numerics consistent with single-GPU baseline).
- python-version: "3.12"
label: "torch 2.8"
torch-pip-args: "torch==2.8.* torchvision==0.23.* torchaudio==2.8.*"
experimental: false
# Upper bound — torch 2.10 is the latest within our <2.11 cap.
# 2.11 was excluded because its default CUDA wheels dropped Volta/Pascal.
- python-version: "3.12"
label: "torch 2.10"
torch-pip-args: "torch==2.10.* torchvision==0.25.* torchaudio==2.10.*"
experimental: false

steps:
- uses: actions/checkout@v4
Expand All @@ -25,15 +52,15 @@ jobs:
- name: Install torch (CPU build)
run: |
python -m pip install --upgrade pip
pip install \
torch==2.5.1+cpu \
torchvision==0.20.1+cpu \
torchaudio==2.5.1+cpu \
pip install ${{ matrix.torch-pip-args }} \
--index-url https://download.pytorch.org/whl/cpu

- name: Install scmidas with dev extras
run: pip install -e ".[dev]"

- name: Show installed torch
run: python -c "import torch; print('torch', torch.__version__)"

- name: Lint (non-blocking)
run: ruff check . || true

Expand Down
26 changes: 26 additions & 0 deletions docs/source/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,32 @@ All notable changes to this project will be documented in this file.

## Version 0.1.x

### v0.1.19 (2026-05-03)
* **📦 Packaging — narrow torch upper bound to `<2.11`**
* torch 2.11 dropped Volta (V100, CC 7.0) and Pascal (P100, GTX
10xx, CC 6.x) from its default `cu128` / `cu129` wheels (to
ship cuDNN 9.15.1, which is incompatible with those archs). On
those GPUs `pip install scmidas==0.1.18` would silently install
a torch that fails at the first CUDA op with
`no kernel image is available for execution on the device`.
* The pin now reads `torch>=2.5,<2.11` (with matching
`torchvision<0.26` / `torchaudio<2.11`). Users on
Ampere/Hopper/Ada/Blackwell GPUs can manually upgrade past the
cap; users on Volta/Pascal stay on a working default install.
* No source-code change — same scmidas as 0.1.18.
* **✨ Enhancements**
* `import scmidas` now runs a one-time GPU self-check: if the
local torch wheel has no kernels for the local GPU, scmidas
emits a `UserWarning` with actionable guidance (downgrade torch
or use the cu126 wheel) instead of the user later seeing a raw
`no kernel image is available` error from somewhere deep in
their training loop. The check no-ops on CPU-only environments
and on working GPU setups.
* **⚙️ CI**
* Test matrix gained a `torch 2.10` job (the new upper bound) and
dropped the previous experimental `torch latest` job. Lower
bound remains `torch 2.5.1` across Python 3.10 / 3.11 / 3.12.

### v0.1.18 (2026-05-02)
* **🐛 Bug Fixes (DDP + mosaic data)**
* Default `sampler_type='auto'` now picks the DDP sampler when a
Expand Down
19 changes: 10 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "scmidas"
version = '0.1.18'
version = '0.1.19'
description = "A torch-based integration method for single-cell multi-omic data."
readme = "README.md"
requires-python = ">=3.10"
Expand All @@ -26,14 +26,15 @@ classifiers = [
# --- Runtime dependencies (minimal but complete for your current imports) ---
dependencies = [
# PyTorch.
# The previous <2.6 cap was a workaround for a suspected Lightning
# DDP incompatibility, but torch 2.8 has since been verified end-to-end
# in the mosaic DDP path (UMAP / numerics consistent with single-GPU).
# Keeping a major-version cap (<3) so a hypothetical breaking 3.x
# release does not silently land for users.
"torch>=2.5,<3",
"torchvision>=0.20,<1",
"torchaudio>=2.5,<3",
# Upper bound is <2.11 because torch 2.11 dropped Volta (V100, CC 7.0)
# and Pascal (P100, GTX 10xx, CC 6.x) from its CUDA 12.8/12.9 wheels
# to ship cuDNN 9.15.1 (which is incompatible with those archs).
# On those GPUs, `pip install scmidas` would silently install a torch
# that fails at the first CUDA op with "no kernel image is available".
# Newer-GPU users (Ampere+) can manually upgrade past this cap.
"torch>=2.5,<2.11",
"torchvision>=0.20,<0.26",
"torchaudio>=2.5,<2.11",

# Lightning (uses lightning.pytorch.utilities.rank_zero_only)
"lightning>=2.4,<2.7",
Expand Down
33 changes: 33 additions & 0 deletions src/scmidas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,36 @@
except PackageNotFoundError:
__version__ = '0.0.0+unknown'
del PackageNotFoundError, _pkg_version


def _check_gpu_compat():
# torch 2.11 dropped Volta (V100, CC 7.0) and Pascal (P100/GTX 10xx,
# CC 6.x) from its default cu128/cu129 wheels. On those GPUs the first
# CUDA op raises "no kernel image is available" — translate that here.
try:
import warnings
import torch
if not torch.cuda.is_available():
return
try:
(torch.zeros(1, device='cuda') + 1).cpu()
except Exception as e:
if 'no kernel image is available' not in str(e):
return
major, minor = torch.cuda.get_device_capability()
warnings.warn(
f"torch {torch.__version__} has no CUDA kernels for your GPU "
f"({torch.cuda.get_device_name(0)}, compute capability "
f"{major}.{minor}). torch 2.11+ dropped Volta/Pascal from its "
f"default cu128/cu129 wheels. Fix: "
f"pip install 'torch<2.11' 'torchvision<0.26' 'torchaudio<2.11' "
f"or use the cu126 wheel via "
f"--index-url https://download.pytorch.org/whl/cu126",
UserWarning, stacklevel=2,
)
except Exception:
pass


_check_gpu_compat()
del _check_gpu_compat
Loading