|
| 1 | +# Copyright (c) MONAI Consortium |
| 2 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 3 | +# you may not use this file except in compliance with the License. |
| 4 | +# You may obtain a copy of the License at |
| 5 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 6 | +# Unless required by applicable law or agreed to in writing, software |
| 7 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 8 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 9 | +# See the License for the specific language governing permissions and |
| 10 | +# limitations under the License. |
| 11 | + |
| 12 | +# MONAI on AMD ROCm (AMD Instinct GPUs). |
| 13 | +# |
| 14 | +# This image installs the upstream `monai` package. |
| 15 | +# |
| 16 | +# docker build -f Dockerfile.rocm -t monai:rocm . |
| 17 | +# |
| 18 | +# docker run --device=/dev/kfd --device=/dev/dri --group-add video \ |
| 19 | +# --ipc=host --shm-size=8g -it monai:rocm |
| 20 | +# |
| 21 | +# Select the GPU architecture with '--build-arg AMDGPU_TARGETS=gfx942|gfx950'. The default is gfx942. |
| 22 | + |
| 23 | +ARG BASE_IMAGE=ubuntu:24.04 |
| 24 | +FROM ${BASE_IMAGE} |
| 25 | + |
| 26 | +LABEL maintainer="monai.contact@gmail.com" |
| 27 | + |
| 28 | +ARG AMDGPU_TARGETS="gfx942" |
| 29 | +ARG ROCM_SERIES="10.0" |
| 30 | +ARG ROCM_INDEX_URL="https://stable.repo.amd.com/rocm/whl-next/" |
| 31 | +# Must match the python3 in BASE_IMAGE: it determines the venv's site-packages path below. |
| 32 | +ARG PYTHON_VERSION=3.12 |
| 33 | + |
| 34 | +ENV DEBIAN_FRONTEND=noninteractive |
| 35 | + |
| 36 | +# ninja-build: required for MONAI's JIT C++/HIP extensions (torch.utils.cpp_extension). |
| 37 | +# libstdc++-13-dev + libopenslide-dev: HIP compile headers and whole-slide-image backend. |
| 38 | +RUN apt-get update \ |
| 39 | + && apt-get install -y --no-install-recommends \ |
| 40 | + ca-certificates curl git openssh-client \ |
| 41 | + python3-venv python3-pip python3-dev \ |
| 42 | + build-essential cmake ninja-build yasm \ |
| 43 | + libgomp1 libstdc++-13-dev \ |
| 44 | + libopenslide-dev libwebp-dev libzstd-dev \ |
| 45 | + && rm -rf /var/lib/apt/lists/* |
| 46 | + |
| 47 | +RUN python3 -m venv /opt/venv |
| 48 | +ENV PATH="/opt/venv/bin:${PATH}" |
| 49 | +RUN pip install --no-cache-dir --upgrade pip wheel |
| 50 | + |
| 51 | +RUN pip install --no-cache-dir --index-url ${ROCM_INDEX_URL} \ |
| 52 | + "rocm[libraries,devel,device-${AMDGPU_TARGETS}]==${ROCM_SERIES}.*" \ |
| 53 | + "torch[device-${AMDGPU_TARGETS}]" \ |
| 54 | + "torchvision[device-${AMDGPU_TARGETS}]" \ |
| 55 | + torchaudio \ |
| 56 | + && rocm-sdk init |
| 57 | + |
| 58 | +ENV ROCM_PATH="/opt/venv/lib/python${PYTHON_VERSION}/site-packages/_rocm_sdk_core" |
| 59 | +ENV ROCM_HOME="${ROCM_PATH}" |
| 60 | +ENV ROCM_DEVEL_PATH="/opt/venv/lib/python${PYTHON_VERSION}/site-packages/_rocm_sdk_devel" |
| 61 | +ENV ROCM_LIBRARIES_PATH="/opt/venv/lib/python${PYTHON_VERSION}/site-packages/_rocm_sdk_libraries" |
| 62 | +ENV PATH="${ROCM_PATH}/bin:${PATH}" |
| 63 | +ENV LD_LIBRARY_PATH="${ROCM_PATH}/lib:${ROCM_PATH}/lib/rocm_sysdeps/lib:${ROCM_PATH}/lib/llvm/lib:${ROCM_LIBRARIES_PATH}/lib" |
| 64 | +ENV CPATH="${ROCM_DEVEL_PATH}/include:/usr/lib/gcc/x86_64-linux-gnu/13/include" |
| 65 | +ENV LIBRARY_PATH="${ROCM_DEVEL_PATH}/lib:${ROCM_PATH}/lib" |
| 66 | +ENV AMDGPU_TARGETS=${AMDGPU_TARGETS} |
| 67 | +ENV PYTORCH_ROCM_ARCH=${AMDGPU_TARGETS} |
| 68 | + |
| 69 | +# hipcc expects bitcode at ROCM_PATH/amdgcn/bitcode; the rocm-sdk wheel places it one level deeper. |
| 70 | +RUN mkdir -p "${ROCM_PATH}/amdgcn" \ |
| 71 | + && ln -sf "${ROCM_PATH}/lib/llvm/amdgcn/bitcode" "${ROCM_PATH}/amdgcn/bitcode" |
| 72 | + |
| 73 | +# Prevent OpenBLAS from spawning one thread per core under MONAI's multiprocessing dataloaders. |
| 74 | +ENV OMP_NUM_THREADS=1 |
| 75 | + |
| 76 | +WORKDIR /opt/monai |
| 77 | + |
| 78 | +COPY LICENSE CHANGELOG.md CODE_OF_CONDUCT.md CONTRIBUTING.md README.md versioneer.py setup.py pyproject.toml runtests.sh MANIFEST.in ./ |
| 79 | +COPY tests ./tests |
| 80 | +COPY monai ./monai |
| 81 | + |
| 82 | +# Use print_dependencies.py rather than -e .[all,testing] to filter CUDA-only packages: |
| 83 | +# cucim-cu* pulls in cuda-toolkit (~1.2 GB); nvidia-ml-py fails at import on ROCm; nni depends on it. |
| 84 | +# BUILD_MONAI=1 builds the C++/HIP extensions ahead of time; FORCE_CUDA=1 is required because the |
| 85 | +# build host has no GPU, so setup.py's `torch.cuda.is_available()` check would otherwise skip them. |
| 86 | +# Compilation itself needs only the toolkit and PYTORCH_ROCM_ARCH (set above), not a device. |
| 87 | +# pytest is not in the "testing" extra; it is added explicitly for running tests by hand. |
| 88 | +RUN python monai/config/print_dependencies.py build-system \ |
| 89 | + | xargs -d '\n' pip install --no-cache-dir --no-build-isolation \ |
| 90 | + && python monai/config/print_dependencies.py all testing \ |
| 91 | + | grep -vE '^cucim-cu|^nvidia-ml-py|^nni' > /tmp/rocm-requirements-$$.txt \ |
| 92 | + && BUILD_MONAI=1 FORCE_CUDA=1 pip install --no-cache-dir --no-build-isolation \ |
| 93 | + -r /tmp/rocm-requirements-$$.txt pytest -e . \ |
| 94 | + && rm -f /tmp/rocm-requirements-$$.txt |
| 95 | + |
| 96 | +# Required at runtime too: monai.config.deviceconfig gates USE_COMPILED on this variable, so |
| 97 | +# without it the extensions built above would be present but never used. |
| 98 | +ENV BUILD_MONAI=1 |
| 99 | + |
| 100 | +# Set HIPCIM_INDEX_URL="" to build without WSI/cucim support. |
| 101 | +# CuImage is imported (not just cucim) because cucim uses lazy_loader -- a bare import |
| 102 | +# succeeds even when the native library is unresolvable. Failing here is deliberate: if |
| 103 | +# hipCIM was requested, an image where the cucim backends silently do not work is worse |
| 104 | +# than no image at all. |
| 105 | +ARG HIPCIM_INDEX_URL="https://pypi.amd.com/rocm-${ROCM_SERIES}.0/simple/" |
| 106 | +RUN if [ -n "${HIPCIM_INDEX_URL}" ]; then \ |
| 107 | + pip install --no-cache-dir --extra-index-url "${HIPCIM_INDEX_URL}" "amd-hipcim" \ |
| 108 | + && python -c "from cucim import CuImage"; \ |
| 109 | + else \ |
| 110 | + echo "hipCIM not installed; whole-slide-image (cucim) backends are unavailable."; \ |
| 111 | + fi |
| 112 | + |
| 113 | +RUN python - <<'PY' |
| 114 | +import torch, monai |
| 115 | +print('MONAI :', monai.__version__) |
| 116 | +print('PyTorch:', torch.__version__) |
| 117 | +print('ROCm :', torch.version.hip) |
| 118 | +try: |
| 119 | + import cucim |
| 120 | + from cucim import CuImage # noqa: F401 |
| 121 | + print('hipCIM :', cucim.__version__) |
| 122 | +except ImportError as exc: |
| 123 | + print('hipCIM : not available (%s)' % exc) |
| 124 | +PY |
| 125 | + |
| 126 | +CMD ["bash"] |
0 commit comments