16031aae96
CPU tests Workflow / Testing (ubuntu-latest, 3.12) (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.13) (push) Failing after 0s
Mypy Type Check / Type Check (push) Failing after 0s
Docs/Test WorkFlow / Test docs build (push) Failing after 1s
PR Conflict Labeler / labeling (push) Failing after 1s
Dependency resolution / Resolve [tflite] extra — Python 3.12 (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.10) (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.13) (push) Failing after 1s
CPU tests Workflow / build-pkg (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.10) (push) Failing after 0s
CPU tests Workflow / Testing (ubuntu-latest, 3.11) (push) Failing after 0s
Smoke Tests / try-all-models (macos-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (macos-latest, 3.13) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / testing-guardian (push) Has been cancelled
GPU tests Workflow / Testing (push) Has been cancelled
69 lines
2.8 KiB
Python
69 lines
2.8 KiB
Python
# ------------------------------------------------------------------------
|
|
# RF-DETR
|
|
# Copyright (c) 2025 Roboflow. All Rights Reserved.
|
|
# Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
|
# ------------------------------------------------------------------------
|
|
"""Tests for the lazy device move running under ``torch.inference_mode()``.
|
|
|
|
``predict()`` stacks ``@torch.inference_mode()`` on top of ``@_ensure_model_on_device``, so the deferred CPU-to-
|
|
accelerator move happens while inference mode is active. Tensors materialised under inference mode are *inference
|
|
tensors*: they can never require gradients, so a later ``train()`` / auto-batch probe silently produces no gradients.
|
|
The move itself must therefore always run with inference mode disabled.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
from typing import Any
|
|
|
|
import torch
|
|
from torch import nn
|
|
|
|
from rfdetr.detr import _move_model_context_to_device
|
|
|
|
|
|
class _RecordingModule(nn.Module):
|
|
"""Module whose ``to()`` records whether inference mode was active at move time."""
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
self.linear = nn.Linear(2, 2)
|
|
self.inference_mode_at_move: bool | None = None
|
|
|
|
def to(self, *args: Any, **kwargs: Any) -> "_RecordingModule":
|
|
"""Record the inference-mode state instead of performing a real device move."""
|
|
self.inference_mode_at_move = torch.is_inference_mode_enabled()
|
|
return self
|
|
|
|
|
|
class TestMoveModelContextUnderInferenceMode:
|
|
"""The deferred device move must never materialise parameters as inference tensors."""
|
|
|
|
def test_moved_params_are_not_inference_tensors(self) -> None:
|
|
"""A real ``.to()`` move inside ``torch.inference_mode()`` must not create inference-tensor parameters."""
|
|
ctx = SimpleNamespace(device=torch.device("meta"), model=nn.Linear(2, 2))
|
|
|
|
with torch.inference_mode():
|
|
_move_model_context_to_device(ctx)
|
|
|
|
assert not any(p.is_inference() for p in ctx.model.parameters())
|
|
|
|
def test_move_still_materializes_on_target_device(self) -> None:
|
|
"""The inference-mode guard must not suppress the device move itself."""
|
|
ctx = SimpleNamespace(device=torch.device("meta"), model=nn.Linear(2, 2))
|
|
|
|
with torch.inference_mode():
|
|
_move_model_context_to_device(ctx)
|
|
|
|
assert all(p.device.type == "meta" for p in ctx.model.parameters())
|
|
|
|
def test_move_runs_with_inference_mode_disabled(self) -> None:
|
|
"""The ``.to()`` call itself must observe inference mode as disabled."""
|
|
module = _RecordingModule()
|
|
ctx = SimpleNamespace(device=torch.device("meta"), model=module)
|
|
|
|
with torch.inference_mode():
|
|
_move_model_context_to_device(ctx)
|
|
|
|
assert module.inference_mode_at_move is False
|