Skip to content
Open
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
3 changes: 1 addition & 2 deletions monai/apps/auto3dseg/bundle_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,7 @@ def _run_cmd(self, cmd: str, devices_info: str = "") -> subprocess.CompletedProc
look_up_option(self.device_setting["MN_START_METHOD"], ["bcprun"])
except ValueError as err:
raise NotImplementedError(
f"{self.device_setting['MN_START_METHOD']} is not supported yet."
"Try modify BundleAlgo._run_cmd for your cluster."
f"{self.device_setting['MN_START_METHOD']} is not supported yet.Try modify BundleAlgo._run_cmd for your cluster."
) from err
Comment on lines 266 to 268
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing space after period in error message.

The concatenation dropped the space between sentences: "not supported yet.Try modify" should be "not supported yet. Try modify".

Proposed fix
             raise NotImplementedError(
-                f"{self.device_setting['MN_START_METHOD']} is not supported yet.Try modify BundleAlgo._run_cmd for your cluster."
+                f"{self.device_setting['MN_START_METHOD']} is not supported yet. Try modify BundleAlgo._run_cmd for your cluster."
             ) from err
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
raise NotImplementedError(
f"{self.device_setting['MN_START_METHOD']} is not supported yet."
"Try modify BundleAlgo._run_cmd for your cluster."
f"{self.device_setting['MN_START_METHOD']} is not supported yet.Try modify BundleAlgo._run_cmd for your cluster."
) from err
raise NotImplementedError(
f"{self.device_setting['MN_START_METHOD']} is not supported yet. Try modify BundleAlgo._run_cmd for your cluster."
) from err
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/apps/auto3dseg/bundle_gen.py` around lines 266 - 268, The error message
raised in BundleAlgo._run_cmd uses a concatenated string missing a space after
the period; update the NotImplementedError text that references
self.device_setting['MN_START_METHOD'] so it reads "...not supported yet. Try
modify BundleAlgo._run_cmd for your cluster." (preserve the current exception
chaining "from err") to fix the missing space between sentences.


return _run_cmd_bcprun(cmd, n=self.device_setting["NUM_NODES"], p=self.device_setting["n_devices"])
Expand Down
5 changes: 2 additions & 3 deletions monai/apps/detection/networks/retinanet_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,7 @@ def set_regular_matcher(
"""
if fg_iou_thresh < bg_iou_thresh:
raise ValueError(
"Require fg_iou_thresh >= bg_iou_thresh. "
f"Got fg_iou_thresh={fg_iou_thresh}, bg_iou_thresh={bg_iou_thresh}."
f"Require fg_iou_thresh >= bg_iou_thresh. Got fg_iou_thresh={fg_iou_thresh}, bg_iou_thresh={bg_iou_thresh}."
)
self.proposal_matcher = Matcher(
fg_iou_thresh, bg_iou_thresh, allow_low_quality_matches=allow_low_quality_matches
Expand Down Expand Up @@ -519,7 +518,7 @@ def forward(
else:
if self.inferer is None:
raise ValueError(
"`self.inferer` is not defined." "Please refer to function self.set_sliding_window_inferer(*)."
"`self.inferer` is not defined.Please refer to function self.set_sliding_window_inferer(*)."
)
Comment on lines 519 to 522
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing space after period in error message.

"is not defined.Please refer" should be "is not defined. Please refer".

Proposed fix
             raise ValueError(
-                "`self.inferer` is not defined.Please refer to function self.set_sliding_window_inferer(*)."
+                "`self.inferer` is not defined. Please refer to function self.set_sliding_window_inferer(*)."
             )
🧰 Tools
🪛 Ruff (0.15.4)

[warning] 520-522: Avoid specifying long messages outside the exception class

(TRY003)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/apps/detection/networks/retinanet_detector.py` around lines 519 - 522,
The error message raised when self.inferer is None contains a missing space
after the period; update the string in the raise ValueError call to insert a
space so it reads "`self.inferer` is not defined. Please refer to function
self.set_sliding_window_inferer(*)" (locate the check referencing self.inferer
and the call to self.set_sliding_window_inferer to apply the fix).

head_outputs = predict_with_inferer(
images, self.network, keys=[self.cls_key, self.box_reg_key], inferer=self.inferer
Expand Down
3 changes: 1 addition & 2 deletions monai/auto3dseg/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,7 @@ def __call__(self, data: dict) -> dict:
self.hist_range = nr_channels * self.hist_range
if len(self.hist_range) != nr_channels:
raise ValueError(
f"There is a mismatch between the number of channels ({nr_channels}) "
f"and histogram ranges ({len(self.hist_range)})."
f"There is a mismatch between the number of channels ({nr_channels}) and histogram ranges ({len(self.hist_range)})."
)

# perform calculation
Expand Down
3 changes: 1 addition & 2 deletions monai/data/wsi_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,7 @@ def get_data(
# Check if there are three color channels for RGB
elif mode in "RGB" and patch.shape[self.channel_dim] != 3:
raise ValueError(
f"The image is expected to have three color channels in '{mode}' mode but has "
f"{patch.shape[self.channel_dim]}. "
f"The image is expected to have three color channels in '{mode}' mode but has {patch.shape[self.channel_dim]}. "
)
# Get patch-related metadata
metadata: dict = self._get_metadata(wsi=each_wsi, patch=patch, location=location, size=size, level=level)
Expand Down
1 change: 0 additions & 1 deletion monai/transforms/regularization/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@


class Mixer(RandomizableTransform):

def __init__(self, batch_size: int, alpha: float = 1.0) -> None:
"""
Mixer is a base class providing the basic logic for the mixup-class of
Expand Down
8 changes: 5 additions & 3 deletions monai/transforms/spatial/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from monai.transforms.croppad.array import CenterSpatialCrop, ResizeWithPadOrCrop
from monai.transforms.inverse import InvertibleTransform
from monai.transforms.spatial.functional import (
_compiled_unsupported,
affine_func,
convert_box_to_points,
convert_points_to_box,
Expand Down Expand Up @@ -2104,14 +2105,15 @@ def __call__(
_align_corners = self.align_corners if align_corners is None else align_corners
img_t, *_ = convert_data_type(img, torch.Tensor, dtype=_dtype, device=_device)
sr = min(len(img_t.peek_pending_shape() if isinstance(img_t, MetaTensor) else img_t.shape[1:]), 3)
_use_compiled = USE_COMPILED and not _compiled_unsupported(img_t.device)
backend, _interp_mode, _padding_mode, _ = resolves_modes(
self.mode if mode is None else mode,
self.padding_mode if padding_mode is None else padding_mode,
backend=None,
use_compiled=USE_COMPILED,
use_compiled=_use_compiled,
)

if USE_COMPILED or backend == TransformBackends.NUMPY:
if _use_compiled or backend == TransformBackends.NUMPY:
grid_t, *_ = convert_to_dst_type(grid[:sr], img_t, dtype=grid.dtype, wrap_sequence=True)
if isinstance(grid, torch.Tensor) and grid_t.data_ptr() == grid.data_ptr():
grid_t = grid_t.clone(memory_format=torch.contiguous_format)
Expand All @@ -2122,7 +2124,7 @@ def __call__(
grid_t[i] = ((_dim - 1) / _dim) * grid_t[i] + t if _align_corners else grid_t[i] + t
elif _align_corners:
grid_t[i] = ((_dim - 1) / _dim) * (grid_t[i] + 0.5)
if USE_COMPILED and backend == TransformBackends.TORCH: # compiled is using torch backend param name
if _use_compiled and backend == TransformBackends.TORCH: # compiled is using torch backend param name
grid_t = moveaxis(grid_t, 0, -1) # type: ignore
out = grid_pull(
img_t.unsqueeze(0),
Expand Down
24 changes: 23 additions & 1 deletion monai/transforms/spatial/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@
__all__ = ["spatial_resample", "orientation", "flip", "resize", "rotate", "zoom", "rotate90", "affine_func"]


def _compiled_unsupported(device: torch.device) -> bool:
"""
Return True if ``monai._C`` (the compiled C extension providing ``grid_pull``) is not
compiled with support for the given CUDA device's compute capability.

``monai._C`` is built at install time against a fixed set of CUDA architectures.
NVIDIA Blackwell GPUs (sm_120, compute capability 12.x) and newer were not included in
the default ``TORCH_CUDA_ARCH_LIST`` when the MONAI slim image was originally built,
so executing ``grid_pull`` on those devices produces incorrect results. Falling back to
the PyTorch-native ``affine_grid`` + ``grid_sample`` path (``USE_COMPILED=False``) gives
correct output on all architectures.

The threshold (``major >= 12``) matches the first architecture family (Blackwell, sm_120)
that shipped after the highest sm supported in the current default build list (sm_90,
Hopper). Adjust this constant when ``monai._C`` is rebuilt with sm_120+ support.
"""
if device.type != "cuda":
return False
return torch.cuda.get_device_properties(device).major >= 12

Comment on lines +57 to +76
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all USE_COMPILED usages that might need the _compiled_unsupported guard
rg -n "USE_COMPILED" --type=py -C2 | grep -v "_compiled_unsupported"

Repository: Project-MONAI/MONAI

Length of output: 22885


🏁 Script executed:

cat -n monai/networks/blocks/warp.py | head -200

Repository: Project-MONAI/MONAI

Length of output: 9110


🏁 Script executed:

sed -n '57,250p' monai/transforms/spatial/functional.py | head -100

Repository: Project-MONAI/MONAI

Length of output: 6288


🏁 Script executed:

sed -n '170,200p' monai/transforms/spatial/functional.py

Repository: Project-MONAI/MONAI

Length of output: 1558


🏁 Script executed:

sed -n '140,152p' monai/networks/blocks/warp.py

Repository: Project-MONAI/MONAI

Length of output: 693


Add device compatibility check before grid_pull call.

The Warp.forward() method (line 141+) calls grid_pull when USE_COMPILED=True without verifying the device supports the compiled C extension. Following the pattern in functional.py (line 183), use:

_use_compiled = USE_COMPILED and not _compiled_unsupported(image.device)
if not _use_compiled:  # pytorch native grid_sample
    ...
else:  # grid_pull
    return grid_pull(...)

This prevents incorrect results on Blackwell GPUs (compute capability 12.x+) where monai._C lacks support.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@monai/transforms/spatial/functional.py` around lines 57 - 76, Warp.forward
currently calls grid_pull when USE_COMPILED is true without checking whether the
compiled C extension supports the device; update Warp.forward to compute
_use_compiled = USE_COMPILED and not _compiled_unsupported(image.device) (reuse
the existing _compiled_unsupported function from functional.py) and branch: if
not _use_compiled use the PyTorch native affine_grid + grid_sample path, else
call grid_pull as before, ensuring grid_pull is only invoked on supported CUDA
devices (reference symbols: Warp.forward, USE_COMPILED, _compiled_unsupported,
grid_pull).


def _maybe_new_metatensor(img, dtype=None, device=None):
"""create a metatensor with fresh metadata if track_meta is True otherwise convert img into a torch tensor"""
return convert_to_tensor(
Expand Down Expand Up @@ -158,7 +179,8 @@ def spatial_resample(
xform_shape = [-1] + in_sp_size
img = img.reshape(xform_shape)
img = img.to(dtype_pt)
if isinstance(mode, int) or USE_COMPILED:
_use_compiled = USE_COMPILED and not _compiled_unsupported(img.device)
if isinstance(mode, int) or _use_compiled:
dst_xform = create_translate(spatial_rank, [float(d - 1) / 2 for d in spatial_size])
xform = xform @ convert_to_dst_type(dst_xform, xform)[0]
affine_xform = monai.transforms.Affine(
Expand Down
Loading