From 0550ce832d4bdac48579696b5b222e16039db1f1 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 25 Apr 2025 12:37:34 +0100 Subject: [PATCH 01/12] Updates for Pytorch 2.7 Signed-off-by: Eric Kerfoot --- .github/workflows/pythonapp-min.yml | 2 +- .github/workflows/pythonapp.yml | 2 +- docs/requirements.txt | 2 +- pyproject.toml | 4 ++-- requirements.txt | 3 +-- setup.cfg | 3 +-- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pythonapp-min.yml b/.github/workflows/pythonapp-min.yml index afc9f6f6d4..7bc2cb38fa 100644 --- a/.github/workflows/pythonapp-min.yml +++ b/.github/workflows/pythonapp-min.yml @@ -124,7 +124,7 @@ jobs: strategy: fail-fast: false matrix: - pytorch-version: ['2.3.1', '2.4.1', '2.5.1', 'latest'] + pytorch-version: ['2.4.1', '2.5.1', '2.6.0', 'latest'] timeout-minutes: 40 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index 5d6fd06afa..536ae6d18a 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -155,7 +155,7 @@ jobs: # install the latest pytorch for testing # however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated # fresh torch installation according to pyproject.toml - python -m pip install torch>=2.3.0 torchvision + python -m pip install torch>=2.4.1 torchvision - name: Check packages run: | pip uninstall monai diff --git a/docs/requirements.txt b/docs/requirements.txt index b314e10640..c5cf0b5baa 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ -f https://download.pytorch.org/whl/cpu/torch-2.3.0%2Bcpu-cp39-cp39-linux_x86_64.whl -torch>=2.3.0 +torch>=2.4.1 pytorch-ignite==0.4.11 numpy>=1.20 itk>=5.2 diff --git a/pyproject.toml b/pyproject.toml index 588d6d22d8..7c76814554 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,14 +2,14 @@ requires = [ "wheel", "setuptools", - "torch>=2.3.0", + "torch>=2.4.1", "ninja", "packaging" ] [tool.black] line-length = 120 -target-version = ['py38', 'py39', 'py310'] +target-version = ['py38', 'py39', 'py310', 'py311', 'py312'] include = '\.pyi?$' exclude = ''' ( diff --git a/requirements.txt b/requirements.txt index ad394ce807..f0d1f54083 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ -torch>=2.3.0; sys_platform != 'win32' -torch>=2.4.1; sys_platform == 'win32' +torch>=2.4.1 numpy>=1.24,<3.0 diff --git a/setup.cfg b/setup.cfg index 622e24abe9..fc415e6cc0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,8 +42,7 @@ setup_requires = ninja packaging install_requires = - torch>=2.3.0; sys_platform != 'win32' - torch>=2.4.1; sys_platform == 'win32' + torch>=2.4.1 numpy>=1.24,<3.0 [options.extras_require] From 00a2dbae4a3ffa9f4b9de811e9b396b59325c052 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 25 Apr 2025 12:47:47 +0100 Subject: [PATCH 02/12] Type fix? Signed-off-by: Eric Kerfoot --- monai/networks/schedulers/ddpm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/networks/schedulers/ddpm.py b/monai/networks/schedulers/ddpm.py index d64e11d379..5cff2c72c6 100644 --- a/monai/networks/schedulers/ddpm.py +++ b/monai/networks/schedulers/ddpm.py @@ -238,7 +238,7 @@ def step( pred_prev_sample = pred_original_sample_coeff * pred_original_sample + current_sample_coeff * sample # 6. Add noise - variance = 0 + variance: int | torch.Tensor = 0 if timestep > 0: noise = torch.randn( model_output.size(), From c978eaea1f6bab16e1717b44cd7f8b63d115aac7 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 25 Apr 2025 12:59:01 +0100 Subject: [PATCH 03/12] Remove py38 reference Signed-off-by: Eric Kerfoot --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7c76814554..76b26731bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ requires = [ [tool.black] line-length = 120 -target-version = ['py38', 'py39', 'py310', 'py311', 'py312'] +target-version = ['py39', 'py310', 'py311', 'py312'] include = '\.pyi?$' exclude = ''' ( From f990ccc1dfddde15a570e62c48ab91fb434d63f6 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Wed, 30 Apr 2025 11:08:57 +0100 Subject: [PATCH 04/12] Try a fix for Windows issue Signed-off-by: Eric Kerfoot --- monai/networks/layers/spatial_transforms.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/monai/networks/layers/spatial_transforms.py b/monai/networks/layers/spatial_transforms.py index 2d39dfdbc1..e8d3598b0d 100644 --- a/monai/networks/layers/spatial_transforms.py +++ b/monai/networks/layers/spatial_transforms.py @@ -12,6 +12,7 @@ from __future__ import annotations from collections.abc import Sequence +import sys import torch import torch.nn as nn @@ -526,6 +527,11 @@ def forward( ValueError: When affine and image batch dimension differ. """ + + # In some cases it's necessary to convert inputs to grid_sample from float64 to float32 to work around known + # issues with PyTorch, see https://github.com/Project-MONAI/MONAI/pull/8429 + convert_f32 = sys.platform != "win32" and src.dtype == torch.float64 and src.device == torch.device("cpu") + # validate `theta` if not isinstance(theta, torch.Tensor): raise TypeError(f"theta must be torch.Tensor but is {type(theta).__name__}.") @@ -582,11 +588,21 @@ def forward( ) grid = nn.functional.affine_grid(theta=theta[:, :sr], size=list(dst_size), align_corners=self.align_corners) + + _input = src.contiguous() + if convert_f32: + _input = _input.to(torch.float32) + grid = grid.to(torch.float32) + dst = nn.functional.grid_sample( - input=src.contiguous(), + input=_input, grid=grid, mode=self.mode, padding_mode=self.padding_mode, align_corners=self.align_corners, ) + + if convert_f32: + dst = dst.to(torch.float64) + return dst From bb15b1f6b734cb22646fabb5fa41dc2c965675bd Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Wed, 30 Apr 2025 11:20:51 +0100 Subject: [PATCH 05/12] Try a fix for Windows issue Signed-off-by: Eric Kerfoot --- monai/networks/layers/spatial_transforms.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/monai/networks/layers/spatial_transforms.py b/monai/networks/layers/spatial_transforms.py index e8d3598b0d..7b4333be36 100644 --- a/monai/networks/layers/spatial_transforms.py +++ b/monai/networks/layers/spatial_transforms.py @@ -11,8 +11,8 @@ from __future__ import annotations -from collections.abc import Sequence import sys +from collections.abc import Sequence import torch import torch.nn as nn @@ -530,7 +530,7 @@ def forward( # In some cases it's necessary to convert inputs to grid_sample from float64 to float32 to work around known # issues with PyTorch, see https://github.com/Project-MONAI/MONAI/pull/8429 - convert_f32 = sys.platform != "win32" and src.dtype == torch.float64 and src.device == torch.device("cpu") + convert_f32 = sys.platform == "win32" and src.dtype == torch.float64 and src.device == torch.device("cpu") # validate `theta` if not isinstance(theta, torch.Tensor): @@ -595,11 +595,7 @@ def forward( grid = grid.to(torch.float32) dst = nn.functional.grid_sample( - input=_input, - grid=grid, - mode=self.mode, - padding_mode=self.padding_mode, - align_corners=self.align_corners, + input=_input, grid=grid, mode=self.mode, padding_mode=self.padding_mode, align_corners=self.align_corners ) if convert_f32: From d10f5182527410aff625fadb446d1016e94ef36a Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Wed, 30 Apr 2025 17:18:45 +0100 Subject: [PATCH 06/12] Try a fix for Windows issue Signed-off-by: Eric Kerfoot --- monai/transforms/spatial/array.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index a75bb390cd..bae4d6e97f 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -14,6 +14,7 @@ from __future__ import annotations +import sys import warnings from collections.abc import Callable, Sequence from copy import deepcopy @@ -2106,13 +2107,28 @@ def __call__( if self.norm_coords: for i, dim in enumerate(img_t.shape[sr + 1 : 0 : -1]): grid_t[0, ..., i] *= 2.0 / max(2, dim) + + # In some cases it's necessary to convert inputs to grid_sample from float64 to float32 to work around known + # issues with PyTorch, see https://github.com/Project-MONAI/MONAI/pull/8429 + convert_f32 = sys.platform == "win32" and img_t.dtype == torch.float64 and img_t.device == torch.device("cpu") + + _img_t = img_t.unsqueeze(0) + + if convert_f32: + _img_t=_img_t.to(torch.float32) + grid_t=grid_t.to(torch.float32) + out = torch.nn.functional.grid_sample( - img_t.unsqueeze(0), + _img_t, grid_t, mode=_interp_mode, padding_mode=_padding_mode, align_corners=None if _align_corners == TraceKeys.NONE else _align_corners, # type: ignore )[0] + + if convert_f32: + out = out.to(torch.float64) + out_val, *_ = convert_to_dst_type(out, dst=img, dtype=np.float32) return out_val From a1f8df9a275c3a2d6dde84c5f89aa754a0aa0d5b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 16:19:12 +0000 Subject: [PATCH 07/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- monai/transforms/spatial/array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index bae4d6e97f..7e844890e0 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -2128,7 +2128,7 @@ def __call__( if convert_f32: out = out.to(torch.float64) - + out_val, *_ = convert_to_dst_type(out, dst=img, dtype=np.float32) return out_val From d2cc08f4f26351a121cda26bb8feed23e624b15d Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Thu, 1 May 2025 23:59:57 +0100 Subject: [PATCH 08/12] Updates to test precision to account for float32 conversion, this should be removed when PyTorch is updated. Signed-off-by: Eric Kerfoot --- environment-dev-test.yml | 14 ++++++++++++++ tests/integration/test_pad_collation.py | 9 ++++++--- tests/lazy_transforms_utils.py | 8 ++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 environment-dev-test.yml diff --git a/environment-dev-test.yml b/environment-dev-test.yml new file mode 100644 index 0000000000..bf69764e58 --- /dev/null +++ b/environment-dev-test.yml @@ -0,0 +1,14 @@ +name: monai +channels: + - pytorch + - defaults + - nvidia + - conda-forge +dependencies: + - numpy>=1.17 + - pytorch>=1.8 + - torchvision + - pytorch-cuda=11.6 + - pip + - pip: + - -r requirements-dev.txt diff --git a/tests/integration/test_pad_collation.py b/tests/integration/test_pad_collation.py index 9d5012c9a3..a236521cd9 100644 --- a/tests/integration/test_pad_collation.py +++ b/tests/integration/test_pad_collation.py @@ -11,8 +11,10 @@ from __future__ import annotations +import os import random import unittest +from contextlib import redirect_stderr from functools import wraps import numpy as np @@ -35,7 +37,7 @@ RandZoomd, ToTensor, ) -from monai.utils import set_determinism +from monai.utils import first, set_determinism @wraps(pad_list_data_collate) @@ -97,8 +99,9 @@ def test_pad_collation(self, t_type, collate_method, transform): # Default collation should raise an error loader_fail = DataLoader(dataset, batch_size=10) with self.assertRaises(RuntimeError): - for _ in loader_fail: - pass + # stifle PyTorch error reporting, we expect failure so don't need to look at it + with open(os.devnull) as f, redirect_stderr(f): + _ = first(loader_fail) # Padded collation shouldn't loader = DataLoader(dataset, batch_size=10, collate_fn=collate_method) diff --git a/tests/lazy_transforms_utils.py b/tests/lazy_transforms_utils.py index 3a737df201..564d9b89f8 100644 --- a/tests/lazy_transforms_utils.py +++ b/tests/lazy_transforms_utils.py @@ -12,6 +12,7 @@ from __future__ import annotations from copy import deepcopy +import sys from monai.data import MetaTensor, set_track_meta from monai.transforms import InvertibleTransform, MapTransform, Randomizable @@ -62,6 +63,13 @@ def test_resampler_lazy( resampler.set_random_state(seed=seed) set_track_meta(True) resampler.lazy = True + + # FIXME: this is a fix for https://github.com/Project-MONAI/MONAI/pull/8429, remove when PyTorch has + # fixed the underlying issue + if sys.platform == "win32": + atol=1e-4 + rtol=1e-4 + pending_output = resampler(**deepcopy(call_param)) if output_idx is not None: expected_output, pending_output = (expected_output[output_idx], pending_output[output_idx]) From 2dc1b31cc25cf4b9b37888dda8e9d52818c81b3a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 23:00:26 +0000 Subject: [PATCH 09/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/lazy_transforms_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lazy_transforms_utils.py b/tests/lazy_transforms_utils.py index 564d9b89f8..c9167cfdad 100644 --- a/tests/lazy_transforms_utils.py +++ b/tests/lazy_transforms_utils.py @@ -66,7 +66,7 @@ def test_resampler_lazy( # FIXME: this is a fix for https://github.com/Project-MONAI/MONAI/pull/8429, remove when PyTorch has # fixed the underlying issue - if sys.platform == "win32": + if sys.platform == "win32": atol=1e-4 rtol=1e-4 From 054bcdcef481a3f173c04a32ae11a3e1d03ae58b Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 2 May 2025 00:01:17 +0100 Subject: [PATCH 10/12] autofix Signed-off-by: Eric Kerfoot --- monai/transforms/spatial/array.py | 8 +++++--- tests/lazy_transforms_utils.py | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/monai/transforms/spatial/array.py b/monai/transforms/spatial/array.py index 7e844890e0..2bb81863b2 100644 --- a/monai/transforms/spatial/array.py +++ b/monai/transforms/spatial/array.py @@ -2110,13 +2110,15 @@ def __call__( # In some cases it's necessary to convert inputs to grid_sample from float64 to float32 to work around known # issues with PyTorch, see https://github.com/Project-MONAI/MONAI/pull/8429 - convert_f32 = sys.platform == "win32" and img_t.dtype == torch.float64 and img_t.device == torch.device("cpu") + convert_f32 = ( + sys.platform == "win32" and img_t.dtype == torch.float64 and img_t.device == torch.device("cpu") + ) _img_t = img_t.unsqueeze(0) if convert_f32: - _img_t=_img_t.to(torch.float32) - grid_t=grid_t.to(torch.float32) + _img_t = _img_t.to(torch.float32) + grid_t = grid_t.to(torch.float32) out = torch.nn.functional.grid_sample( _img_t, diff --git a/tests/lazy_transforms_utils.py b/tests/lazy_transforms_utils.py index 564d9b89f8..29e755aaab 100644 --- a/tests/lazy_transforms_utils.py +++ b/tests/lazy_transforms_utils.py @@ -11,8 +11,8 @@ from __future__ import annotations -from copy import deepcopy import sys +from copy import deepcopy from monai.data import MetaTensor, set_track_meta from monai.transforms import InvertibleTransform, MapTransform, Randomizable @@ -66,9 +66,9 @@ def test_resampler_lazy( # FIXME: this is a fix for https://github.com/Project-MONAI/MONAI/pull/8429, remove when PyTorch has # fixed the underlying issue - if sys.platform == "win32": - atol=1e-4 - rtol=1e-4 + if sys.platform == "win32": + atol = 1e-4 + rtol = 1e-4 pending_output = resampler(**deepcopy(call_param)) if output_idx is not None: From 5a537cd04d4edeb74922fb66be814f4d3d74f42d Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 2 May 2025 00:43:23 +0100 Subject: [PATCH 11/12] Remove extra file Signed-off-by: Eric Kerfoot --- environment-dev-test.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 environment-dev-test.yml diff --git a/environment-dev-test.yml b/environment-dev-test.yml deleted file mode 100644 index bf69764e58..0000000000 --- a/environment-dev-test.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: monai -channels: - - pytorch - - defaults - - nvidia - - conda-forge -dependencies: - - numpy>=1.17 - - pytorch>=1.8 - - torchvision - - pytorch-cuda=11.6 - - pip - - pip: - - -r requirements-dev.txt From b3b1c38810b620f51686a54cf7e5af0dbf03ba48 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Fri, 2 May 2025 13:10:35 +0100 Subject: [PATCH 12/12] Attempt pytype fix Signed-off-by: Eric Kerfoot --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 00674990d1..890eaebfd0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -20,7 +20,7 @@ pyflakes black>=22.12 isort>=5.1, <6.0 ruff -pytype>=2020.6.1; platform_system != "Windows" +pytype>=2020.6.1, <=2024.4.11; platform_system != "Windows" types-setuptools mypy>=1.5.0, <1.12.0 ninja