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
2 changes: 1 addition & 1 deletion Dockerfile.rocm
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ ENV BUILD_MONAI=1
# than no image at all.
ARG HIPCIM_INDEX_URL="https://pypi.amd.com/rocm-${ROCM_SERIES}.0/simple/"
RUN if [ -n "${HIPCIM_INDEX_URL}" ]; then \
pip install --no-cache-dir --extra-index-url "${HIPCIM_INDEX_URL}" "amd-hipcim" \
pip install --no-cache-dir --extra-index-url "${HIPCIM_INDEX_URL}" "amd-hipcim>=26.6.0" \
&& python -c "from cucim import CuImage"; \
else \
echo "hipCIM not installed; whole-slide-image (cucim) backends are unavailable."; \
Expand Down
32 changes: 29 additions & 3 deletions docs/source/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ pip install monai
MONAI supports the extras syntax such as `pip install 'monai[nibabel]'`. The options are

```text
clearml, cucim, cupy, einops, fire, gdown, h5py, huggingface_hub, hyena, ignite, imagecodecs, itk, jsonschema, lmdb, lpips, matplotlib, metrics_reloaded, mlflow, nibabel, nni, nvimgcodec, onnx, openslide, optuna, pandas, pillow, polygraphy, psutil, pyamg, pybind11, pydicom, pynrrd, pynvml, pyyaml, requests, segment_anything, scipy, skimage, tensorboard, tensorboardX, tifffile, torchio, torchvision, tqdm, transformers, zarr
clearml, cucim, cupy, einops, fire, gdown, h5py, huggingface_hub, hyena, ignite, imagecodecs, itk, jsonschema, lmdb, lpips, matplotlib, metrics_reloaded, mlflow, nibabel, nni, nvimgcodec, onnx, openslide, optuna, pandas, pillow, polygraphy, psutil, pyamg, pybind11, pydicom, pynrrd, pynvml, pyyaml, requests, rocm, segment_anything, scipy, skimage, tensorboard, tensorboardX, tifffile, torchio, torchvision, tqdm, transformers, zarr
```

which correspond to the packages: `clearml`, `cucim` (`cucim-cu12` or `cucim-cu13`), `cupy-cuda13x`, `einops`, `fire`, `gdown`, `h5py`, `huggingface_hub`, `nvsubquadratic`, `omegaconf`, `pytorch-ignite`, `imagecodecs`, `itk`, `jsonschema`, `lmdb`, `lpips`, `matplotlib`, `MetricsReloaded`, `mlflow`, `nibabel`, `nni`, `filelock`, `nvidia-nvimgcodec-cu13`, `onnx`, `onnxruntime`, `onnx_graphsurgeon`, `onnxscript`, `openslide-python`, `openslide-bin`, `optuna`, `pandas`, `pillow`, `polygraphy`, `psutil`, `pyamg`, `pybind11`, `pydicom`, `pynrrd`, `nvidia-ml-py`, `pyyaml`, `requests`, `segment_anything`, `scipy`, `scikit-image`, `tensorboard`, `tensorboardX`, `tifffile`, `torchio`, `torchvision`, `tqdm`, `transformers`, `zarr`.
which correspond to the packages: `clearml`, `cucim` (`cucim-cu12` or `cucim-cu13`), `cupy-cuda13x`, `einops`, `fire`, `gdown`, `h5py`, `huggingface_hub`, `nvsubquadratic`, `omegaconf`, `pytorch-ignite`, `imagecodecs`, `itk`, `jsonschema`, `lmdb`, `lpips`, `matplotlib`, `MetricsReloaded`, `mlflow`, `nibabel`, `nni`, `filelock`, `nvidia-nvimgcodec-cu13`, `onnx`, `onnxruntime`, `onnx_graphsurgeon`, `onnxscript`, `openslide-python`, `openslide-bin`, `optuna`, `pandas`, `pillow`, `polygraphy`, `psutil`, `pyamg`, `pybind11`, `pydicom`, `pynrrd`, `nvidia-ml-py`, `pyyaml`, `requests`, `amd-hipcim`, `segment_anything`, `scipy`, `scikit-image`, `tensorboard`, `tensorboardX`, `tifffile`, `torchio`, `torchvision`, `tqdm`, `transformers`, `zarr`.

Almost all of these can be installed together with the `all` option. For development on MONAI, this should be accompanied by `testing` which will install the testing static checking packages. Cupy and `nvimgcodec` are omitted from `all` since the choice between
Cuda 12 and 13 versions of the libraries can't be resolved when installing and must be manually installed.
Expand All @@ -89,6 +89,30 @@ The `nvimgcodec` extra installs GPU-accelerated DICOM decoding for `NvImgCodecPy
(`pip install 'monai[nvimgcodec]'`). It is Linux-only in the extra definition; CUDA 13 is the
default. CUDA 12 users should install matching `cupy-cuda12x` and `nvidia-nvimgcodec-cu12` wheels.

The `rocm` extra provides the AMD ROCm counterparts of the CUDA-only imaging dependencies:
[`amd-hipcim`](https://rocm.docs.amd.com/projects/hipCIM/en/latest/) (hipCIM), which pulls
`amd-cupy` in transitively. `amd-hipcim` ships the `cucim` Python namespace, so all existing MONAI
code that imports from `cucim` (e.g. `WSIReader` with `backend="cucim"`) works on ROCm without any
code changes. This extra covers MONAI's optional imaging dependencies only: a ROCm build of PyTorch
and the matching ROCm runtime must already be installed, see
[PyTorch on ROCm](https://rocm.docs.amd.com/projects/ai-ecosystem/en/latest/frameworks/pytorch/install.html).
Both `amd-hipcim` and `amd-cupy` are published on AMD's package index rather than PyPI, so an extra
index URL matching your ROCm series is required:

```bash
pip install --extra-index-url https://pypi.amd.com/rocm-10.0.0/simple/ 'monai[rocm]'
```

AMD currently publishes these wheels for CPython 3.12 on x86_64 Linux only; on other interpreters or
architectures the install fails with `No matching distribution found for amd-hipcim`.

Do not use `monai[all]` on ROCm: the `all` extra includes CUDA-only sub-extras (`cucim`, `cupy`,
`nvimgcodec`, `pynvml`, `hyena`) that pull in `cupy-cuda13x`, `cuda-toolkit`, and a cascade of
`nvidia-*` packages that will not work on ROCm. `Dockerfile.rocm` in the repo root shows how to
install the full optional dependency set on ROCm while filtering those packages — follow it as the
authoritative reference for the complete environment setup (library paths, compiler flags,
`rocm-sdk init`, and the full container recipe).

The `hyena` extra pulls in [`nvsubquadratic`](https://github.com/NVIDIA-BioNeMo/nvSubquadratic),
required by `HyenaNDUNETR` / `HyenaMixer` / `HyenaTransformerBlock` (subquadratic
O(N log N) alternatives to windowed self-attention). Install with
Expand Down Expand Up @@ -333,8 +357,10 @@ MONAI itself:
```bash
git clone https://github.com/Project-MONAI/MONAI.git
cd MONAI/
python monai/config/print_dependencies.py \* > requirements.txt
python monai/config/print_dependencies.py all testing > requirements.txt
pip install -r requirements.txt
# Note: `all testing` is used rather than `*` because `*` now also includes the `rocm` extra,
# which requires AMD's package index and is not resolvable from PyPI.
```

To install all optional dependencies with `conda` based on MONAI development environment settings (`environment-dev.yml`;
Expand Down
6 changes: 5 additions & 1 deletion monai/config/check_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ def check_torch_cuda():
"""
import torch

fprint("CUDA version:", torch.version.cuda)
# `torch.version.cuda` is None on a ROCm build, where the toolkit version is `torch.version.hip`.
if torch.version.hip:
fprint("HIP version:", torch.version.hip)
else:
fprint("CUDA version:", torch.version.cuda)

try:
dcount = torch.cuda.device_count()
Expand Down
7 changes: 6 additions & 1 deletion monai/config/deviceconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,12 @@ def get_gpu_info() -> OrderedDict:
_dict_append(output, "Has CUDA", lambda: bool(torch.cuda.is_available()))

if output["Has CUDA"]:
_dict_append(output, "CUDA version", lambda: torch.version.cuda)
# On a ROCm build `torch.version.cuda` is None and `torch.version.hip` carries the toolkit
# version. Reporting "CUDA version: None" is misleading, so the key name switches with the build.
if torch.version.hip:
_dict_append(output, "HIP version", lambda: torch.version.hip)
else:
_dict_append(output, "CUDA version", lambda: torch.version.cuda)
cudnn_ver = torch.backends.cudnn.version()
_dict_append(output, "cuDNN enabled", lambda: bool(cudnn_ver))
_dict_append(output, "NVIDIA_TF32_OVERRIDE", os.environ.get("NVIDIA_TF32_OVERRIDE"))
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ pynrrd = ["pynrrd"]
pynvml = ["nvidia-ml-py"]
pyyaml = ["pyyaml"]
requests = ["requests"]
# hipCIM is the ROCm counterpart of `cucim`; it pulls `amd-cupy` in transitively. Omitted from `all`:
# the real wheels live on AMD's package index, not PyPI, so an `--extra-index-url` is needed (see
# installation.md). The floor pins the first AMD-index release, skipping the PyPI placeholder stub.
rocm = ["amd-hipcim>=26.6.0; platform_system == 'Linux'"]
# per #5882 this requirement must be on one line to get removed by sed in weekly-preview.yml
segment_anything = ["segment_anything @ git+https://github.com/facebookresearch/segment-anything.git@6fdee8f2727f4506cfbbe553e23b895e27956588"]
scipy = ["scipy>=1.12.0"]
Expand Down
35 changes: 35 additions & 0 deletions tests/config/test_print_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@

from __future__ import annotations

import sys
import unittest
from io import StringIO
from unittest.mock import patch

from monai.config import print_debug_info
from monai.config.deviceconfig import get_gpu_info


class TestPrintInfo(unittest.TestCase):
Expand All @@ -24,6 +27,38 @@ def test_print_info(self):
print_debug_info(file=out)
self.assertGreater(out.tell(), 0)

@patch("torch.backends.cudnn.version", lambda: 0)
@patch("torch.cuda.device_count", lambda: 0)
@patch("torch.cuda.is_available", lambda: True)
@patch("torch.version.hip", "7.0.0")
def test_hip_version(self):
"""A ROCm build reports the HIP version, where `torch.version.cuda` would be None."""
output = get_gpu_info()
self.assertEqual(output["HIP version"], "7.0.0")
self.assertNotIn("CUDA version", output)

@patch("torch.backends.cudnn.version", lambda: 0)
@patch("torch.cuda.device_count", lambda: 0)
@patch("torch.cuda.is_available", lambda: True)
@patch("torch.version.hip", None)
@patch("torch.version.cuda", "12.4")
def test_cuda_version(self):
"""A CUDA build is unaffected and still reports the CUDA version."""
output = get_gpu_info()
self.assertEqual(output["CUDA version"], "12.4")
self.assertNotIn("HIP version", output)

@patch("torch.version.hip", "7.0.0")
def test_check_env_hip_version(self):
"""check_env.check_torch_cuda() prints 'HIP version:' on a ROCm build."""
import monai.config.check_env as ce

buf = StringIO()
with patch.object(sys, "stdout", buf):
ce.check_torch_cuda()
self.assertIn("HIP version:", buf.getvalue())
self.assertNotIn("CUDA version:", buf.getvalue())


if __name__ == "__main__":
unittest.main()
Loading