Skip to content

Commit

Permalink
Bump torch to 1.13.1 to mitigate CVE-2022-45907 unsafe usage of eval
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesobutler committed Jan 12, 2025
1 parent 1c00ea2 commit d2e989f
Show file tree
Hide file tree
Showing 30 changed files with 55 additions and 533 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,12 @@ jobs:
strategy:
matrix:
environment:
- "PT110+CUDA113"
- "PT113+CUDA118"
- "PT210+CUDA121"
- "PT240+CUDA126"
- "PTLATEST+CUDA126"
include:
# https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes
- environment: PT110+CUDA113
pytorch: "torch==1.10.2 torchvision==0.11.3 --extra-index-url https://download.pytorch.org/whl/cu113"
base: "nvcr.io/nvidia/pytorch:21.06-py3" # CUDA 11.3
- environment: PT113+CUDA118
pytorch: "torch==1.13.1 torchvision==0.14.1 --extra-index-url https://download.pytorch.org/whl/cu121"
base: "nvcr.io/nvidia/pytorch:22.10-py3" # CUDA 11.8
Expand Down
16 changes: 1 addition & 15 deletions .github/workflows/pythonapp-gpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,10 @@ jobs:
strategy:
matrix:
environment:
- "PT19+CUDA114DOCKER"
- "PT110+CUDA111"
- "PT112+CUDA118DOCKER"
- "PT113+CUDA116"
- "PT210+CUDA121DOCKER"
include:
# https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes
- environment: PT110+CUDA111
pytorch: "torch==1.10.2 torchvision==0.11.3 --extra-index-url https://download.pytorch.org/whl/cu111"
base: "nvcr.io/nvidia/cuda:11.1.1-devel-ubuntu18.04"
- environment: PT112+CUDA118DOCKER
# 22.09: 1.13.0a0+d0d6b1f
pytorch: "-h" # we explicitly set pytorch to -h to avoid pip install error
base: "nvcr.io/nvidia/pytorch:22.09-py3"
- environment: PT113+CUDA116
pytorch: "torch==1.13.1 torchvision==0.14.1"
base: "nvcr.io/nvidia/cuda:11.6.1-devel-ubuntu18.04"
Expand All @@ -59,8 +49,7 @@ jobs:
apt-get update
apt-get install -y wget
if [ ${{ matrix.environment }} = "PT110+CUDA111" ] || \
[ ${{ matrix.environment }} = "PT113+CUDA116" ]
if [ ${{ matrix.environment }} = "PT113+CUDA116" ]
then
PYVER=3.9 PYSFX=3 DISTUTILS=python3-distutils && \
apt-get update && apt-get install -y --no-install-recommends \
Expand Down Expand Up @@ -94,9 +83,6 @@ jobs:
python get-pip.py && \
rm get-pip.py;
fi
- if: matrix.environment == 'PT19+CUDA114DOCKER'
name: Optional Cupy dependency (cuda114)
run: echo "cupy-cuda114" >> requirements-dev.txt
- name: Install dependencies
if: github.event.pull_request.merged != true
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pythonapp-min.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
strategy:
fail-fast: false
matrix:
pytorch-version: ['1.10.2', '1.11.0', '1.12.1', '1.13', '2.0.1', 'latest']
pytorch-version: ['1.13.1', '2.0.1', 'latest']
timeout-minutes: 40
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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>=1.9 torchvision
python -m pip install torch>=1.13.1 torchvision
- name: Check packages
run: |
pip uninstall monai
Expand Down
4 changes: 2 additions & 2 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-f https://download.pytorch.org/whl/cpu/torch-1.12.1%2Bcpu-cp37-cp37m-linux_x86_64.whl
torch>=1.9
-f https://download.pytorch.org/whl/cpu/torch-1.13.1%2Bcpu-cp39-cp39-linux_x86_64.whl
torch>=1.13.1
pytorch-ignite==0.4.11
numpy>=1.20
itk>=5.2
Expand Down
2 changes: 1 addition & 1 deletion environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ channels:
- conda-forge
dependencies:
- numpy>=1.24,<2.0
- pytorch>=1.9
- pytorch>=1.13.1
- torchio
- torchvision
- pytorch-cuda>=11.6
Expand Down
3 changes: 1 addition & 2 deletions monai/apps/auto3dseg/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import torch

from monai.config import KeysCollection
from monai.networks.utils import pytorch_after
from monai.transforms import MapTransform
from monai.utils.misc import ImageMetaKey

Expand Down Expand Up @@ -76,7 +75,7 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> dict[Hashable, torc
d[key] = torch.nn.functional.interpolate(
input=d[key].unsqueeze(0),
size=image_shape,
mode="nearest-exact" if pytorch_after(1, 11) else "nearest",
mode="nearest-exact",
).squeeze(0)
else:
raise ValueError(
Expand Down
19 changes: 6 additions & 13 deletions monai/data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
issequenceiterable,
look_up_option,
optional_import,
pytorch_after,
)

pd, _ = optional_import("pandas")
Expand Down Expand Up @@ -450,12 +449,9 @@ def collate_meta_tensor_fn(batch, *, collate_fn_map=None):
Collate a sequence of meta tensor into a single batched metatensor. This is called by `collage_meta_tensor`
and so should not be used as a collate function directly in dataloaders.
"""
if pytorch_after(1, 13):
from torch.utils.data._utils.collate import collate_tensor_fn # imported here for pylint/mypy issues
from torch.utils.data._utils.collate import collate_tensor_fn # imported here for pylint/mypy issues

collated = collate_tensor_fn(batch)
else:
collated = default_collate(batch)
collated = collate_tensor_fn(batch)

meta_dicts = [i.meta or TraceKeys.NONE for i in batch]
common_ = set.intersection(*[set(d.keys()) for d in meta_dicts if isinstance(d, dict)])
Expand Down Expand Up @@ -494,18 +490,15 @@ def list_data_collate(batch: Sequence):
Need to use this collate if apply some transforms that can generate batch data.
"""
from torch.utils.data._utils.collate import default_collate_fn_map

if pytorch_after(1, 13):
# needs to go here to avoid circular import
from torch.utils.data._utils.collate import default_collate_fn_map

from monai.data.meta_tensor import MetaTensor
from monai.data.meta_tensor import MetaTensor

default_collate_fn_map.update({MetaTensor: collate_meta_tensor_fn})
default_collate_fn_map.update({MetaTensor: collate_meta_tensor_fn})
elem = batch[0]
data = [i for k in batch for i in k] if isinstance(elem, list) else batch
key = None
collate_fn = default_collate if pytorch_after(1, 13) else collate_meta_tensor
collate_fn = default_collate
try:
if config.USE_META_DICT:
data = pickle_operations(data) # bc 0.9.0
Expand Down
3 changes: 1 addition & 2 deletions monai/inferers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@
fall_back_tuple,
look_up_option,
optional_import,
pytorch_after,
)

tqdm, _ = optional_import("tqdm", name="tqdm")
_nearest_mode = "nearest-exact" if pytorch_after(1, 11) else "nearest"
_nearest_mode = "nearest-exact"

__all__ = ["sliding_window_inference"]

Expand Down
18 changes: 4 additions & 14 deletions monai/losses/dice.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from monai.losses.spatial_mask import MaskedLoss
from monai.losses.utils import compute_tp_fp_fn
from monai.networks import one_hot
from monai.utils import DiceCEReduction, LossReduction, Weight, look_up_option, pytorch_after
from monai.utils import DiceCEReduction, LossReduction, Weight, look_up_option


class DiceLoss(_Loss):
Expand Down Expand Up @@ -738,20 +738,16 @@ def __init__(
batch=batch,
weight=dice_weight,
)
if pytorch_after(1, 10):
self.cross_entropy = nn.CrossEntropyLoss(
weight=weight, reduction=reduction, label_smoothing=label_smoothing
)
else:
self.cross_entropy = nn.CrossEntropyLoss(weight=weight, reduction=reduction)
self.cross_entropy = nn.CrossEntropyLoss(
weight=weight, reduction=reduction, label_smoothing=label_smoothing
)
self.binary_cross_entropy = nn.BCEWithLogitsLoss(pos_weight=weight, reduction=reduction)
if lambda_dice < 0.0:
raise ValueError("lambda_dice should be no less than 0.0.")
if lambda_ce < 0.0:
raise ValueError("lambda_ce should be no less than 0.0.")
self.lambda_dice = lambda_dice
self.lambda_ce = lambda_ce
self.old_pt_ver = not pytorch_after(1, 10)

def ce(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
"""
Expand All @@ -764,12 +760,6 @@ def ce(self, input: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
if n_pred_ch != n_target_ch and n_target_ch == 1:
target = torch.squeeze(target, dim=1)
target = target.long()
elif self.old_pt_ver:
warnings.warn(
f"Multichannel targets are not supported in this older Pytorch version {torch.__version__}. "
"Using argmax (as a workaround) to convert target to a single channel."
)
target = torch.argmax(target, dim=1)
elif not torch.is_floating_point(target):
target = target.to(dtype=input.dtype)

Expand Down
4 changes: 1 addition & 3 deletions monai/losses/ds_loss.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import torch.nn.functional as F
from torch.nn.modules.loss import _Loss

from monai.utils import pytorch_after


class DeepSupervisionLoss(_Loss):
"""
Expand All @@ -42,7 +40,7 @@ def __init__(self, loss: _Loss, weight_mode: str = "exp", weights: list[float] |
self.loss = loss
self.weight_mode = weight_mode
self.weights = weights
self.interp_mode = "nearest-exact" if pytorch_after(1, 11) else "nearest"
self.interp_mode = "nearest-exact"

def get_weights(self, levels: int = 1) -> list[float]:
"""
Expand Down
16 changes: 2 additions & 14 deletions monai/networks/layers/simplelayers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
issequenceiterable,
look_up_option,
optional_import,
pytorch_after,
)

_C, _ = optional_import("monai._C")
Expand Down Expand Up @@ -293,14 +292,7 @@ def apply_filter(x: torch.Tensor, kernel: torch.Tensor, **kwargs) -> torch.Tenso
x = x.view(1, kernel.shape[0], *spatials)
conv = [F.conv1d, F.conv2d, F.conv3d][n_spatial - 1]
if "padding" not in kwargs:
if pytorch_after(1, 10):
kwargs["padding"] = "same"
else:
# even-sized kernels are not supported
kwargs["padding"] = [(k - 1) // 2 for k in kernel.shape[2:]]
elif kwargs["padding"] == "same" and not pytorch_after(1, 10):
# even-sized kernels are not supported
kwargs["padding"] = [(k - 1) // 2 for k in kernel.shape[2:]]
kwargs["padding"] = "same"

if "stride" not in kwargs:
kwargs["stride"] = 1
Expand Down Expand Up @@ -372,11 +364,7 @@ def _make_coeffs(window_length, order):
a = idx ** torch.arange(order + 1, dtype=torch.float, device="cpu").reshape(-1, 1)
y = torch.zeros(order + 1, dtype=torch.float, device="cpu")
y[0] = 1.0
return (
torch.lstsq(y, a).solution.squeeze() # type: ignore
if not pytorch_after(1, 11)
else torch.linalg.lstsq(a, y).solution.squeeze()
)
return torch.linalg.lstsq(a, y).solution.squeeze()


class HilbertTransform(nn.Module):
Expand Down
20 changes: 4 additions & 16 deletions monai/networks/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from monai.apps.utils import get_logger
from monai.config import PathLike
from monai.utils.misc import ensure_tuple, save_obj, set_determinism
from monai.utils.module import look_up_option, optional_import, pytorch_after
from monai.utils.module import look_up_option, optional_import
from monai.utils.type_conversion import convert_to_dst_type, convert_to_tensor

onnx, _ = optional_import("onnx")
Expand Down Expand Up @@ -676,15 +676,6 @@ def convert_to_onnx(
torch_versioned_kwargs["verify"] = verify
verify = False
else:
if not pytorch_after(1, 10):
if "example_outputs" not in kwargs:
# https://github.com/pytorch/pytorch/blob/release/1.9/torch/onnx/__init__.py#L182
raise TypeError(
"example_outputs is required in scripting mode before PyTorch 1.10."
"Please provide example outputs or use trace mode to export onnx model."
)
torch_versioned_kwargs["example_outputs"] = kwargs["example_outputs"]
del kwargs["example_outputs"]
mode_to_export = torch.jit.script(model, **kwargs)

if torch.is_tensor(inputs) or isinstance(inputs, dict):
Expand Down Expand Up @@ -746,8 +737,7 @@ def convert_to_onnx(
# compare onnx/ort and PyTorch results
for r1, r2 in zip(torch_out, onnx_out):
if isinstance(r1, torch.Tensor):
assert_fn = torch.testing.assert_close if pytorch_after(1, 11) else torch.testing.assert_allclose
assert_fn(r1.cpu(), convert_to_tensor(r2, dtype=r1.dtype), rtol=rtol, atol=atol) # type: ignore
torch.testing.assert_close(r1.cpu(), convert_to_tensor(r2, dtype=r1.dtype), rtol=rtol, atol=atol) # type: ignore

return onnx_model

Expand Down Expand Up @@ -817,8 +807,7 @@ def convert_to_torchscript(
# compare TorchScript and PyTorch results
for r1, r2 in zip(torch_out, torchscript_out):
if isinstance(r1, torch.Tensor) or isinstance(r2, torch.Tensor):
assert_fn = torch.testing.assert_close if pytorch_after(1, 11) else torch.testing.assert_allclose
assert_fn(r1, r2, rtol=rtol, atol=atol) # type: ignore
torch.testing.assert_close(r1, r2, rtol=rtol, atol=atol) # type: ignore

return script_module

Expand Down Expand Up @@ -1031,8 +1020,7 @@ def convert_to_trt(
# compare TorchScript and PyTorch results
for r1, r2 in zip(torch_out, trt_out):
if isinstance(r1, torch.Tensor) or isinstance(r2, torch.Tensor):
assert_fn = torch.testing.assert_close if pytorch_after(1, 11) else torch.testing.assert_allclose
assert_fn(r1, r2, rtol=rtol, atol=atol) # type: ignore
torch.testing.assert_close(r1, r2, rtol=rtol, atol=atol) # type: ignore

return trt_model

Expand Down
7 changes: 1 addition & 6 deletions monai/transforms/croppad/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
ensure_tuple_rep,
fall_back_tuple,
look_up_option,
pytorch_after,
)

__all__ = [
Expand Down Expand Up @@ -392,11 +391,7 @@ def compute_slices(
roi_center_t = convert_to_tensor(data=roi_center, dtype=torch.int16, wrap_sequence=True, device="cpu")
roi_size_t = convert_to_tensor(data=roi_size, dtype=torch.int16, wrap_sequence=True, device="cpu")
_zeros = torch.zeros_like(roi_center_t)
half = (
torch.divide(roi_size_t, 2, rounding_mode="floor")
if pytorch_after(1, 8)
else torch.floor_divide(roi_size_t, 2)
)
half = torch.divide(roi_size_t, 2, rounding_mode="floor")
roi_start_t = torch.maximum(roi_center_t - half, _zeros)
roi_end_t = torch.maximum(roi_start_t + roi_size_t, roi_start_t)
else:
Expand Down
3 changes: 1 addition & 2 deletions monai/transforms/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
look_up_option,
min_version,
optional_import,
pytorch_after,
unsqueeze_left,
unsqueeze_right,
)
Expand Down Expand Up @@ -2255,7 +2254,7 @@ def _to_torch_resample_interp_mode(interp_mode):
if ret is not None:
return ret
_mapping = {
SplineMode.ZERO: InterpolateMode.NEAREST_EXACT if pytorch_after(1, 11) else InterpolateMode.NEAREST,
SplineMode.ZERO: InterpolateMode.NEAREST_EXACT,
SplineMode.ONE: InterpolateMode.LINEAR,
SplineMode.THREE: InterpolateMode.BICUBIC,
}
Expand Down
10 changes: 0 additions & 10 deletions monai/utils/tf32.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,6 @@ def detect_default_tf32() -> bool:
if not has_ampere_or_later():
return False

from monai.utils.module import pytorch_after

if pytorch_after(1, 7, 0) and not pytorch_after(1, 12, 0):
warnings.warn(
"torch.backends.cuda.matmul.allow_tf32 = True by default.\n"
" This value defaults to True when PyTorch version in [1.7, 1.11] and may affect precision.\n"
" See https://docs.monai.io/en/latest/precision_accelerating.html#precision-and-accelerating"
)
may_enable_tf32 = True

override_tf32_env_vars = {"NVIDIA_TF32_OVERRIDE": "1"} # TORCH_ALLOW_TF32_CUBLAS_OVERRIDE not checked #6907
for name, override_val in override_tf32_env_vars.items():
if os.environ.get(name) == override_val:
Expand Down
Loading

0 comments on commit d2e989f

Please sign in to comment.