1818
1919import torch
2020
21+ from monai ._C import max_compute_capability as _max_cc
2122from monai .transforms .spatial .functional import _compiled_unsupported
2223
2324
25+ def _has_sm120_support () -> bool :
26+ """Return True if the compiled _C extension includes sm_120 (cc 12.0) support."""
27+ return _max_cc () >= 1200
28+
29+
2430class TestCompiledUnsupported (unittest .TestCase ):
2531 """Test _compiled_unsupported device detection."""
2632
@@ -31,14 +37,17 @@ def test_cpu_device_always_supported(self):
3137
3238 @unittest .skipIf (not torch .cuda .is_available (), reason = "CUDA not available" )
3339 def test_cuda_device_detection (self ):
34- """Verify CUDA compute capability detection."""
40+ """Verify CUDA compute capability detection against compiled arch list ."""
3541 device = torch .device ("cuda:0" )
36- cc_major = torch .cuda .get_device_properties (device ).major
37- unsupported = _compiled_unsupported (device )
38- if cc_major >= 12 :
39- self .assertTrue (unsupported )
42+ cc = torch .cuda .get_device_properties (device )
43+ device_cc = cc .major * 100 + cc .minor
44+ max_cc = _max_cc ()
45+ if max_cc == 0 :
46+ # No build info — rely on heuristic
47+ expected = cc .major >= 12
4048 else :
41- self .assertFalse (unsupported )
49+ expected = device_cc > max_cc
50+ self .assertEqual (_compiled_unsupported (device ), expected )
4251
4352 def test_compiled_unsupported_return_type (self ):
4453 """Verify return type is bool."""
@@ -51,17 +60,30 @@ class TestResampleFallback(unittest.TestCase):
5160 """Test Resample fallback behavior on unsupported devices."""
5261
5362 def test_resample_compilation_flag_respected (self ):
54- """Verify _compiled_unsupported identifies Blackwell (cc>=12) and supported (cc<12) devices ."""
63+ """Verify _compiled_unsupported compares device CC against compiled arch list ."""
5564 mock_props = MagicMock ()
5665 cuda_device = torch .device ("cuda:0" )
5766
58- mock_props .major = 12 # Blackwell – unsupported
59- with patch ("torch.cuda.get_device_properties" , return_value = mock_props ):
60- self .assertTrue (_compiled_unsupported (cuda_device ))
67+ max_cc = _max_cc ()
68+ if max_cc == 0 :
69+ # No build info — use old heuristic
70+ mock_props .major = 12 # Blackwell
71+ with patch ("torch.cuda.get_device_properties" , return_value = mock_props ):
72+ self .assertTrue (_compiled_unsupported (cuda_device ))
73+
74+ mock_props .major = 9 # Hopper
75+ with patch ("torch.cuda.get_device_properties" , return_value = mock_props ):
76+ self .assertFalse (_compiled_unsupported (cuda_device ))
77+ else :
78+ # With build info: device_cc > max_cc means unsupported
79+ mock_props .major = max_cc // 100
80+ mock_props .minor = max_cc % 100
81+ with patch ("torch.cuda.get_device_properties" , return_value = mock_props ):
82+ self .assertFalse (_compiled_unsupported (cuda_device ))
6183
62- mock_props .major = 9 # Hopper – supported
63- with patch ("torch.cuda.get_device_properties" , return_value = mock_props ):
64- self .assertFalse (_compiled_unsupported (cuda_device ))
84+ mock_props .major = max_cc // 100 + 2 # beyond compiled range
85+ with patch ("torch.cuda.get_device_properties" , return_value = mock_props ):
86+ self .assertTrue (_compiled_unsupported (cuda_device ))
6587
6688 def test_compiled_unsupported_logic (self ):
6789 """Test that unsupported devices are correctly detected."""
@@ -70,10 +92,14 @@ def test_compiled_unsupported_logic(self):
7092
7193 cuda_device = torch .device ("cuda:0" if torch .cuda .is_available () else "cpu" )
7294 if cuda_device .type == "cuda" :
73- cc_major = torch .cuda .get_device_properties (cuda_device ).major
74- expected = cc_major >= 12
75- actual = _compiled_unsupported (cuda_device )
76- self .assertEqual (actual , expected )
95+ cc = torch .cuda .get_device_properties (cuda_device )
96+ device_cc = cc .major * 100 + cc .minor
97+ max_cc = _max_cc ()
98+ if max_cc == 0 :
99+ expected = cc .major >= 12
100+ else :
101+ expected = device_cc > max_cc
102+ self .assertEqual (_compiled_unsupported (cuda_device ), expected )
77103
78104
79105if __name__ == "__main__" :
0 commit comments