Skip to content

Commit 2e391c8

Browse files
authored
Bump torch minimum to mitigate CVE-2024-31580 & CVE-2024-31583 and enable numpy 2 compatibility (#8368)
This is a follow-up to the comments made in #8296 (comment). ### Description This bumps the minimum required `torch` version from 1.13.1 to 2.2.0 in the first commit. See GHSA-5pcm-hx3q-hm94 and GHSA-pg7h-5qx3-wjr3 for more details regarding the "High" severity scoring. - https://nvd.nist.gov/vuln/detail/CVE-2024-31580 - https://nvd.nist.gov/vuln/detail/CVE-2024-31583 Additionally, PyTorch added support for numpy 2 starting with PyTorch 2.3.0. The second commit in this PR allows for numpy 1 or numpy 2 to be used with torch>=2.3.0. I have included this commit in this PR as upgrading to torch 2.2 means you might as well update to 2.3 to get the numpy 2 compatibility. A special case is being handled on Windows as PyTorch Windows binaries had compatibilities issues with numpy 2 that were fixed in torch 2.4.1 (see pytorch/pytorch#131668 (comment)). Maintainers will need to update the required status checks for the [`dev`](https://github.com/Project-MONAI/MONAI/tree/dev) branch to: - Remove min-dep-pytorch (2.0.1) ### Types of changes <!--- Put an `x` in all the boxes that apply, and remove the not applicable items --> - [X] Breaking change (fix or new feature that would cause existing functionality to change). - [ ] Integration tests passed locally by running `./runtests.sh -f -u --net --coverage`. - [ ] Quick tests passed locally by running `./runtests.sh --quick --unittests --disttests`. --------- Signed-off-by: James Butler <[email protected]>
1 parent a09c1f0 commit 2e391c8

17 files changed

+48
-79
lines changed

.github/workflows/cron.yml

+3-7
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,13 @@ jobs:
1313
strategy:
1414
matrix:
1515
environment:
16-
- "PT113+CUDA118"
17-
- "PT210+CUDA121"
16+
- "PT230+CUDA121"
1817
- "PT240+CUDA126"
1918
- "PTLATEST+CUDA126"
2019
include:
2120
# https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes
22-
- environment: PT113+CUDA118
23-
pytorch: "torch==1.13.1 torchvision==0.14.1 --extra-index-url https://download.pytorch.org/whl/cu121"
24-
base: "nvcr.io/nvidia/pytorch:22.10-py3" # CUDA 11.8
25-
- environment: PT210+CUDA121
26-
pytorch: "pytorch==2.1.0 torchvision==0.16.0 --extra-index-url https://download.pytorch.org/whl/cu121"
21+
- environment: PT230+CUDA121
22+
pytorch: "pytorch==2.3.0 torchvision==0.18.0 --extra-index-url https://download.pytorch.org/whl/cu121"
2723
base: "nvcr.io/nvidia/pytorch:23.08-py3" # CUDA 12.1
2824
- environment: PT240+CUDA126
2925
pytorch: "pytorch==2.4.0 torchvision==0.19.0 --extra-index-url https://download.pytorch.org/whl/cu121"

.github/workflows/pythonapp-gpu.yml

+14-12
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,21 @@ jobs:
2222
strategy:
2323
matrix:
2424
environment:
25-
- "PT113+CUDA116"
26-
- "PT210+CUDA121DOCKER"
25+
- "PT230+CUDA124DOCKER"
26+
- "PT240+CUDA125DOCKER"
27+
- "PT250+CUDA126DOCKER"
2728
include:
2829
# https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes
29-
- environment: PT113+CUDA116
30-
pytorch: "torch==1.13.1 torchvision==0.14.1"
31-
base: "nvcr.io/nvidia/cuda:11.6.1-devel-ubuntu18.04"
32-
- environment: PT210+CUDA121DOCKER
33-
# 23.08: 2.1.0a0+29c30b1
30+
- environment: PT230+CUDA124DOCKER
31+
# 24.04: 2.3.0a0+6ddf5cf85e
3432
pytorch: "-h" # we explicitly set pytorch to -h to avoid pip install error
35-
base: "nvcr.io/nvidia/pytorch:23.08-py3"
36-
- environment: PT210+CUDA121DOCKER
37-
# 24.08: 2.3.0a0+40ec155e58.nv24.3
33+
base: "nvcr.io/nvidia/pytorch:24.04-py3"
34+
- environment: PT240+CUDA125DOCKER
35+
# 24.06: 2.4.0a0+f70bd71a48
36+
pytorch: "-h" # we explicitly set pytorch to -h to avoid pip install error
37+
base: "nvcr.io/nvidia/pytorch:24.06-py3"
38+
- environment: PT250+CUDA126DOCKER
39+
# 24.08: 2.5.0a0+872d972e41
3840
pytorch: "-h" # we explicitly set pytorch to -h to avoid pip install error
3941
base: "nvcr.io/nvidia/pytorch:24.08-py3"
4042
container:
@@ -49,7 +51,7 @@ jobs:
4951
apt-get update
5052
apt-get install -y wget
5153
52-
if [ ${{ matrix.environment }} = "PT113+CUDA116" ]
54+
if [ ${{ matrix.environment }} = "PT230+CUDA124" ]
5355
then
5456
PYVER=3.9 PYSFX=3 DISTUTILS=python3-distutils && \
5557
apt-get update && apt-get install -y --no-install-recommends \
@@ -114,7 +116,7 @@ jobs:
114116
# build for the current self-hosted CI Tesla V100
115117
BUILD_MONAI=1 TORCH_CUDA_ARCH_LIST="7.0" ./runtests.sh --build --disttests
116118
./runtests.sh --quick --unittests
117-
if [ ${{ matrix.environment }} = "PT113+CUDA116" ]; then
119+
if [ ${{ matrix.environment }} = "PT230+CUDA124" ]; then
118120
# test the clang-format tool downloading once
119121
coverage run -m tests.clang_format_utils
120122
fi

.github/workflows/pythonapp-min.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ jobs:
124124
strategy:
125125
fail-fast: false
126126
matrix:
127-
pytorch-version: ['1.13.1', '2.0.1', '2.2.2', '2.3.1', '2.4.1', 'latest']
127+
pytorch-version: ['2.3.1', '2.4.1', '2.5.1', 'latest']
128128
timeout-minutes: 40
129129
steps:
130130
- uses: actions/checkout@v4

.github/workflows/pythonapp.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494
- if: runner.os == 'windows'
9595
name: Install torch cpu from pytorch.org (Windows only)
9696
run: |
97-
python -m pip install torch==1.13.1+cpu torchvision==0.14.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
97+
python -m pip install torch==2.4.1 torchvision==0.19.1+cpu --index-url https://download.pytorch.org/whl/cpu
9898
- if: runner.os == 'Linux'
9999
name: Install itk pre-release (Linux only)
100100
run: |
@@ -103,7 +103,7 @@ jobs:
103103
- name: Install the dependencies
104104
run: |
105105
python -m pip install --user --upgrade pip wheel
106-
python -m pip install torch==1.13.1 torchvision==0.14.1
106+
python -m pip install torch==2.4.1 torchvision==0.19.1
107107
cat "requirements-dev.txt"
108108
python -m pip install -r requirements-dev.txt
109109
python -m pip list
@@ -155,7 +155,7 @@ jobs:
155155
# install the latest pytorch for testing
156156
# however, "pip install monai*.tar.gz" will build cpp/cuda with an isolated
157157
# fresh torch installation according to pyproject.toml
158-
python -m pip install torch>=1.13.1 torchvision
158+
python -m pip install torch>=2.3.0 torchvision
159159
- name: Check packages
160160
run: |
161161
pip uninstall monai

docs/requirements.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
-f https://download.pytorch.org/whl/cpu/torch-1.13.1%2Bcpu-cp39-cp39-linux_x86_64.whl
2-
torch>=1.13.1
1+
-f https://download.pytorch.org/whl/cpu/torch-2.3.0%2Bcpu-cp39-cp39-linux_x86_64.whl
2+
torch>=2.3.0
33
pytorch-ignite==0.4.11
44
numpy>=1.20
55
itk>=5.2

environment-dev.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ channels:
55
- nvidia
66
- conda-forge
77
dependencies:
8-
- numpy>=1.24,<2.0
9-
- pytorch>=1.13.1
8+
- numpy>=1.24,<3.0
9+
- pytorch>=2.3.0
1010
- torchio
1111
- torchvision
1212
- pytorch-cuda>=11.6

monai/engines/evaluator.py

+3-8
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from monai.utils import ForwardMode, IgniteInfo, ensure_tuple, min_version, optional_import
2929
from monai.utils.enums import CommonKeys as Keys
3030
from monai.utils.enums import EngineStatsKeys as ESKeys
31-
from monai.utils.module import look_up_option, pytorch_after
31+
from monai.utils.module import look_up_option
3232

3333
if TYPE_CHECKING:
3434
from ignite.engine import Engine, EventEnum
@@ -269,13 +269,8 @@ def __init__(
269269
amp_kwargs=amp_kwargs,
270270
)
271271
if compile:
272-
if pytorch_after(2, 1):
273-
compile_kwargs = {} if compile_kwargs is None else compile_kwargs
274-
network = torch.compile(network, **compile_kwargs) # type: ignore[assignment]
275-
else:
276-
warnings.warn(
277-
"Network compilation (compile=True) not supported for Pytorch versions before 2.1, no compilation done"
278-
)
272+
compile_kwargs = {} if compile_kwargs is None else compile_kwargs
273+
network = torch.compile(network, **compile_kwargs) # type: ignore[assignment]
279274
self.network = network
280275
self.compile = compile
281276
self.inferer = SimpleInferer() if inferer is None else inferer

monai/engines/trainer.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from monai.utils import AdversarialIterationEvents, AdversarialKeys, GanKeys, IgniteInfo, min_version, optional_import
2828
from monai.utils.enums import CommonKeys as Keys
2929
from monai.utils.enums import EngineStatsKeys as ESKeys
30-
from monai.utils.module import pytorch_after
3130

3231
if TYPE_CHECKING:
3332
from ignite.engine import Engine, EventEnum
@@ -183,13 +182,8 @@ def __init__(
183182
amp_kwargs=amp_kwargs,
184183
)
185184
if compile:
186-
if pytorch_after(2, 1):
187-
compile_kwargs = {} if compile_kwargs is None else compile_kwargs
188-
network = torch.compile(network, **compile_kwargs) # type: ignore[assignment]
189-
else:
190-
warnings.warn(
191-
"Network compilation (compile=True) not supported for Pytorch versions before 2.1, no compilation done"
192-
)
185+
compile_kwargs = {} if compile_kwargs is None else compile_kwargs
186+
network = torch.compile(network, **compile_kwargs) # type: ignore[assignment]
193187
self.network = network
194188
self.compile = compile
195189
self.optimizer = optimizer

monai/networks/blocks/crossattention.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import torch.nn as nn
1818

1919
from monai.networks.layers.utils import get_rel_pos_embedding_layer
20-
from monai.utils import optional_import, pytorch_after
20+
from monai.utils import optional_import
2121

2222
Rearrange, _ = optional_import("einops.layers.torch", name="Rearrange")
2323

@@ -84,11 +84,6 @@ def __init__(
8484
if causal and sequence_length is None:
8585
raise ValueError("sequence_length is necessary for causal attention.")
8686

87-
if use_flash_attention and not pytorch_after(minor=13, major=1, patch=0):
88-
raise ValueError(
89-
"use_flash_attention is only supported for PyTorch versions >= 2.0."
90-
"Upgrade your PyTorch or set the flag to False."
91-
)
9287
if use_flash_attention and save_attn:
9388
raise ValueError(
9489
"save_attn has been set to True, but use_flash_attention is also set"

monai/networks/blocks/selfattention.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import torch.nn.functional as F
1919

2020
from monai.networks.layers.utils import get_rel_pos_embedding_layer
21-
from monai.utils import optional_import, pytorch_after
21+
from monai.utils import optional_import
2222

2323
Rearrange, _ = optional_import("einops.layers.torch", name="Rearrange")
2424

@@ -90,11 +90,6 @@ def __init__(
9090
if causal and sequence_length is None:
9191
raise ValueError("sequence_length is necessary for causal attention.")
9292

93-
if use_flash_attention and not pytorch_after(minor=13, major=1, patch=0):
94-
raise ValueError(
95-
"use_flash_attention is only supported for PyTorch versions >= 2.0."
96-
"Upgrade your PyTorch or set the flag to False."
97-
)
9893
if use_flash_attention and save_attn:
9994
raise ValueError(
10095
"save_attn has been set to True, but use_flash_attention is also set"

monai/networks/blocks/upsample.py

+3-11
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import torch.nn as nn
1818

1919
from monai.networks.layers.factories import Conv, Pad, Pool
20-
from monai.networks.utils import CastTempType, icnr_init, pixelshuffle
21-
from monai.utils import InterpolateMode, UpsampleMode, ensure_tuple_rep, look_up_option, pytorch_after
20+
from monai.networks.utils import icnr_init, pixelshuffle
21+
from monai.utils import InterpolateMode, UpsampleMode, ensure_tuple_rep, look_up_option
2222

2323
__all__ = ["Upsample", "UpSample", "SubpixelUpsample", "Subpixelupsample", "SubpixelUpSample"]
2424

@@ -164,15 +164,7 @@ def __init__(
164164
align_corners=align_corners,
165165
)
166166

167-
# Cast to float32 as 'upsample_nearest2d_out_frame' op does not support bfloat16
168-
# https://github.com/pytorch/pytorch/issues/86679. This issue is solved in PyTorch 2.1
169-
if pytorch_after(major=2, minor=1):
170-
self.add_module("upsample_non_trainable", upsample)
171-
else:
172-
self.add_module(
173-
"upsample_non_trainable",
174-
CastTempType(initial_type=torch.bfloat16, temporary_type=torch.float32, submodule=upsample),
175-
)
167+
self.add_module("upsample_non_trainable", upsample)
176168
if post_conv:
177169
self.add_module("postconv", post_conv)
178170
elif up_mode == UpsampleMode.PIXELSHUFFLE:

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
requires = [
33
"wheel",
44
"setuptools",
5-
"torch>=1.13.1",
5+
"torch>=2.3.0",
66
"ninja",
77
"packaging"
88
]

requirements.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
torch>=1.13.1,<2.6
2-
numpy>=1.24,<2.0
1+
torch>=2.3.0,<2.6; sys_platform != 'win32'
2+
torch>=2.4.1,<2.6; sys_platform == 'win32'
3+
numpy>=1.24,<3.0

setup.cfg

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ setup_requires =
4242
ninja
4343
packaging
4444
install_requires =
45-
torch>=1.13.1
46-
numpy>=1.24,<2.0
45+
torch>=2.3.0; sys_platform != 'win32'
46+
torch>=2.4.1; sys_platform == 'win32'
47+
numpy>=1.24,<3.0
4748

4849
[options.extras_require]
4950
all =

tests/integration/test_integration_bundle_run.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ def test_tiny(self):
7676
)
7777
with open(meta_file, "w") as f:
7878
json.dump(
79-
{"version": "0.1.0", "monai_version": "1.1.0", "pytorch_version": "1.13.1", "numpy_version": "1.22.2"},
80-
f,
79+
{"version": "0.1.0", "monai_version": "1.1.0", "pytorch_version": "2.3.0", "numpy_version": "1.22.2"}, f
8180
)
8281
cmd = ["coverage", "run", "-m", "monai.bundle"]
8382
# test both CLI entry "run" and "run_workflow"
@@ -114,8 +113,7 @@ def test_scripts_fold(self):
114113
)
115114
with open(meta_file, "w") as f:
116115
json.dump(
117-
{"version": "0.1.0", "monai_version": "1.1.0", "pytorch_version": "1.13.1", "numpy_version": "1.22.2"},
118-
f,
116+
{"version": "0.1.0", "monai_version": "1.1.0", "pytorch_version": "2.3.0", "numpy_version": "1.22.2"}, f
119117
)
120118

121119
os.mkdir(scripts_dir)

tests/metrics/test_surface_dice.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def test_tolerance_euclidean_distance_with_spacing(self):
8282
expected_res0[1, 1] = np.nan
8383
for b, c in np.ndindex(batch_size, n_class):
8484
np.testing.assert_allclose(expected_res0[b, c], res0[b, c].cpu())
85-
np.testing.assert_array_equal(agg0.cpu(), np.nanmean(np.nanmean(expected_res0, axis=1), axis=0))
85+
np.testing.assert_allclose(agg0.cpu(), np.nanmean(np.nanmean(expected_res0, axis=1), axis=0))
8686
np.testing.assert_equal(not_nans.cpu(), torch.tensor(2))
8787

8888
def test_tolerance_euclidean_distance(self):
@@ -126,7 +126,7 @@ def test_tolerance_euclidean_distance(self):
126126
expected_res0[1, 1] = np.nan
127127
for b, c in np.ndindex(batch_size, n_class):
128128
np.testing.assert_allclose(expected_res0[b, c], res0[b, c].cpu())
129-
np.testing.assert_array_equal(agg0.cpu(), np.nanmean(np.nanmean(expected_res0, axis=1), axis=0))
129+
np.testing.assert_allclose(agg0.cpu(), np.nanmean(np.nanmean(expected_res0, axis=1), axis=0))
130130
np.testing.assert_equal(not_nans.cpu(), torch.tensor(2))
131131

132132
def test_tolerance_euclidean_distance_3d(self):
@@ -173,7 +173,7 @@ def test_tolerance_euclidean_distance_3d(self):
173173
expected_res0[1, 1] = np.nan
174174
for b, c in np.ndindex(batch_size, n_class):
175175
np.testing.assert_allclose(expected_res0[b, c], res0[b, c].cpu())
176-
np.testing.assert_array_equal(agg0.cpu(), np.nanmean(np.nanmean(expected_res0, axis=1), axis=0))
176+
np.testing.assert_allclose(agg0.cpu(), np.nanmean(np.nanmean(expected_res0, axis=1), axis=0))
177177
np.testing.assert_equal(not_nans.cpu(), torch.tensor(2))
178178

179179
def test_tolerance_all_distances(self):

tests/nonconfig_workflow.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def initialize(self):
6565
self._monai_version = "1.1.0"
6666

6767
if self._pytorch_version is None:
68-
self._pytorch_version = "1.13.1"
68+
self._pytorch_version = "2.3.0"
6969

7070
if self._numpy_version is None:
7171
self._numpy_version = "1.22.2"

0 commit comments

Comments
 (0)