From 0347fdb123e9b30d002003856db7186606cfaff4 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Thu, 23 Dec 2021 22:18:05 +0000 Subject: [PATCH 1/2] has cupy check Signed-off-by: Wenqi Li --- tests/test_cast_to_type.py | 6 +++--- tests/test_cast_to_typed.py | 5 +++-- tests/test_cucim_dict_transform.py | 6 +++--- tests/test_cucim_transform.py | 6 +++--- tests/test_nvtx_decorator.py | 4 ++-- tests/test_rand_cucim_dict_transform.py | 6 +++--- tests/test_rand_cucim_transform.py | 6 +++--- tests/test_to_cupy.py | 6 +++--- tests/test_to_cupyd.py | 10 +++------- tests/test_to_numpy.py | 6 +++--- tests/test_to_numpyd.py | 6 +++--- tests/test_to_tensor.py | 6 +++--- tests/utils.py | 21 +++++++++++++++++++++ 13 files changed, 56 insertions(+), 38 deletions(-) diff --git a/tests/test_cast_to_type.py b/tests/test_cast_to_type.py index eac4aabf29..82daabc4e7 100644 --- a/tests/test_cast_to_type.py +++ b/tests/test_cast_to_type.py @@ -18,9 +18,9 @@ from monai.transforms import CastToType from monai.utils import optional_import from monai.utils.type_conversion import get_equivalent_dtype -from tests.utils import TEST_NDARRAYS +from tests.utils import HAS_CUPY, TEST_NDARRAYS -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") TESTS = [] for p in TEST_NDARRAYS: @@ -45,7 +45,7 @@ def test_type(self, out_dtype, input_data, expected_type): self.assertEqual(result.dtype, get_equivalent_dtype(expected_type, type(result))) @parameterized.expand(TESTS_CUPY) - @unittest.skipUnless(has_cp, "Requires CuPy") + @unittest.skipUnless(HAS_CUPY, "Requires CuPy") def test_type_cupy(self, out_dtype, input_data, expected_type): input_data = cp.asarray(input_data) diff --git a/tests/test_cast_to_typed.py b/tests/test_cast_to_typed.py index 8662b0bfe3..4c7623a9e0 100644 --- a/tests/test_cast_to_typed.py +++ b/tests/test_cast_to_typed.py @@ -17,8 +17,9 @@ from monai.transforms import CastToTyped from monai.utils import optional_import +from tests.utils import HAS_CUPY -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") TEST_CASE_1 = [ {"keys": ["img"], "dtype": np.float64}, @@ -58,7 +59,7 @@ def test_type(self, input_param, input_data, expected_type): self.assertEqual(v.dtype, expected_type[k]) @parameterized.expand(TESTS_CUPY) - @unittest.skipUnless(has_cp, "Requires CuPy") + @unittest.skipUnless(HAS_CUPY, "Requires CuPy") def test_type_cupy(self, input_param, input_data, expected_type): input_data = {k: cp.asarray(v) for k, v in input_data.items()} diff --git a/tests/test_cucim_dict_transform.py b/tests/test_cucim_dict_transform.py index 1a20f88562..f8b54c3147 100644 --- a/tests/test_cucim_dict_transform.py +++ b/tests/test_cucim_dict_transform.py @@ -16,10 +16,10 @@ from monai.transforms import CuCIMd from monai.utils import optional_import, set_determinism -from tests.utils import skip_if_no_cuda +from tests.utils import HAS_CUPY, skip_if_no_cuda _, has_cut = optional_import("cucim.core.operations.expose.transform") -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") set_determinism(seed=0) @@ -62,7 +62,7 @@ @skip_if_no_cuda -@unittest.skipUnless(has_cp, "CuPy is required.") +@unittest.skipUnless(HAS_CUPY, "CuPy is required.") @unittest.skipUnless(has_cut, "cuCIM transforms are required.") class TestCuCIMDict(unittest.TestCase): @parameterized.expand( diff --git a/tests/test_cucim_transform.py b/tests/test_cucim_transform.py index 6833dde4b7..2bf9791bce 100644 --- a/tests/test_cucim_transform.py +++ b/tests/test_cucim_transform.py @@ -16,10 +16,10 @@ from monai.transforms import CuCIM from monai.utils import optional_import, set_determinism -from tests.utils import skip_if_no_cuda +from tests.utils import HAS_CUPY, skip_if_no_cuda _, has_cut = optional_import("cucim.core.operations.expose.transform") -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") set_determinism(seed=0) @@ -62,7 +62,7 @@ @skip_if_no_cuda -@unittest.skipUnless(has_cp, "CuPy is required.") +@unittest.skipUnless(HAS_CUPY, "CuPy is required.") @unittest.skipUnless(has_cut, "cuCIM transforms are required.") class TestCuCIM(unittest.TestCase): @parameterized.expand( diff --git a/tests/test_nvtx_decorator.py b/tests/test_nvtx_decorator.py index ef5c1c8260..e81c72efcf 100644 --- a/tests/test_nvtx_decorator.py +++ b/tests/test_nvtx_decorator.py @@ -31,9 +31,9 @@ ToTensorD, ) from monai.utils import Range, optional_import +from tests.utils import HAS_CUPY _, has_nvtx = optional_import("torch._C._nvtx", descriptor="NVTX is not installed. Are you sure you have a CUDA build?") -_, has_cp = optional_import("cupy") _, has_tvt = optional_import("torchvision.transforms") _, has_cut = optional_import("cucim.core.operations.expose.transform") @@ -103,7 +103,7 @@ def test_tranform_dict(self, input): np.testing.assert_equal(output.numpy(), output3.numpy()) @parameterized.expand([TEST_CASE_WRAPPER]) - @unittest.skipUnless(has_cp, "Requires CuPy.") + @unittest.skipUnless(HAS_CUPY, "Requires CuPy.") @unittest.skipUnless(has_cut, "Requires cuCIM transforms.") @unittest.skipUnless(has_tvt, "Requires torchvision transforms.") def test_wrapper_tranforms(self, input): diff --git a/tests/test_rand_cucim_dict_transform.py b/tests/test_rand_cucim_dict_transform.py index e27e11b7e3..cd41b7f49a 100644 --- a/tests/test_rand_cucim_dict_transform.py +++ b/tests/test_rand_cucim_dict_transform.py @@ -16,10 +16,10 @@ from monai.transforms import RandCuCIMd from monai.utils import optional_import, set_determinism -from tests.utils import skip_if_no_cuda +from tests.utils import HAS_CUPY, skip_if_no_cuda _, has_cut = optional_import("cucim.core.operations.expose.transform") -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") set_determinism(seed=0) @@ -74,7 +74,7 @@ @skip_if_no_cuda -@unittest.skipUnless(has_cp, "CuPy is required.") +@unittest.skipUnless(HAS_CUPY, "CuPy is required.") @unittest.skipUnless(has_cut, "cuCIM transforms are required.") class TestRandCuCIMDict(unittest.TestCase): @parameterized.expand( diff --git a/tests/test_rand_cucim_transform.py b/tests/test_rand_cucim_transform.py index a205e639f3..0950329833 100644 --- a/tests/test_rand_cucim_transform.py +++ b/tests/test_rand_cucim_transform.py @@ -16,10 +16,10 @@ from monai.transforms import RandCuCIM from monai.utils import optional_import, set_determinism -from tests.utils import skip_if_no_cuda +from tests.utils import HAS_CUPY, skip_if_no_cuda _, has_cut = optional_import("cucim.core.operations.expose.transform") -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") set_determinism(seed=0) @@ -74,7 +74,7 @@ @skip_if_no_cuda -@unittest.skipUnless(has_cp, "CuPy is required.") +@unittest.skipUnless(HAS_CUPY, "CuPy is required.") @unittest.skipUnless(has_cut, "cuCIM transforms are required.") class TestRandCuCIM(unittest.TestCase): @parameterized.expand( diff --git a/tests/test_to_cupy.py b/tests/test_to_cupy.py index e936fd8538..36edf24f3f 100644 --- a/tests/test_to_cupy.py +++ b/tests/test_to_cupy.py @@ -17,12 +17,12 @@ from monai.transforms import ToCupy from monai.utils import optional_import -from tests.utils import skip_if_no_cuda +from tests.utils import HAS_CUPY, skip_if_no_cuda -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") -@skipUnless(has_cp, "CuPy is required.") +@skipUnless(HAS_CUPY, "CuPy is required.") class TestToCupy(unittest.TestCase): def test_cupy_input(self): test_data = cp.array([[1, 2], [3, 4]], dtype=cp.float32) diff --git a/tests/test_to_cupyd.py b/tests/test_to_cupyd.py index 3de0da16a3..3e778ae269 100644 --- a/tests/test_to_cupyd.py +++ b/tests/test_to_cupyd.py @@ -17,13 +17,13 @@ from monai.transforms import ToCupyd from monai.utils import optional_import -from tests.utils import skip_if_no_cuda +from tests.utils import HAS_CUPY, skip_if_no_cuda -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") +@skipUnless(HAS_CUPY, "CuPy is required.") class TestToCupyd(unittest.TestCase): - @skipUnless(has_cp, "CuPy is required.") def test_cupy_input(self): test_data = cp.array([[1, 2], [3, 4]]) test_data = cp.rot90(test_data) @@ -33,7 +33,6 @@ def test_cupy_input(self): self.assertTrue(result.flags["C_CONTIGUOUS"]) cp.testing.assert_allclose(result, test_data) - @skipUnless(has_cp, "CuPy is required.") def test_numpy_input(self): test_data = np.array([[1, 2], [3, 4]]) test_data = np.rot90(test_data) @@ -43,7 +42,6 @@ def test_numpy_input(self): self.assertTrue(result.flags["C_CONTIGUOUS"]) cp.testing.assert_allclose(result, test_data) - @skipUnless(has_cp, "CuPy is required.") def test_tensor_input(self): test_data = torch.tensor([[1, 2], [3, 4]]) test_data = test_data.rot90() @@ -53,7 +51,6 @@ def test_tensor_input(self): self.assertTrue(result.flags["C_CONTIGUOUS"]) cp.testing.assert_allclose(result, test_data.numpy()) - @skipUnless(has_cp, "CuPy is required.") @skip_if_no_cuda def test_tensor_cuda_input(self): test_data = torch.tensor([[1, 2], [3, 4]]).cuda() @@ -64,7 +61,6 @@ def test_tensor_cuda_input(self): self.assertTrue(result.flags["C_CONTIGUOUS"]) cp.testing.assert_allclose(result, test_data.cpu().numpy()) - @skipUnless(has_cp, "CuPy is required.") def test_list_tuple(self): test_data = [[1, 2], [3, 4]] result = ToCupyd(keys="img", wrap_sequence=True)({"img": test_data})["img"] diff --git a/tests/test_to_numpy.py b/tests/test_to_numpy.py index bc04566213..e1f135a289 100644 --- a/tests/test_to_numpy.py +++ b/tests/test_to_numpy.py @@ -17,13 +17,13 @@ from monai.transforms import ToNumpy from monai.utils import optional_import -from tests.utils import assert_allclose, skip_if_no_cuda +from tests.utils import HAS_CUPY, assert_allclose, skip_if_no_cuda -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") class TestToNumpy(unittest.TestCase): - @skipUnless(has_cp, "CuPy is required.") + @skipUnless(HAS_CUPY, "CuPy is required.") def test_cupy_input(self): test_data = cp.array([[1, 2], [3, 4]]) test_data = cp.rot90(test_data) diff --git a/tests/test_to_numpyd.py b/tests/test_to_numpyd.py index 22d1a0507e..ba7cf798ef 100644 --- a/tests/test_to_numpyd.py +++ b/tests/test_to_numpyd.py @@ -17,13 +17,13 @@ from monai.transforms import ToNumpyd from monai.utils import optional_import -from tests.utils import assert_allclose, skip_if_no_cuda +from tests.utils import HAS_CUPY, assert_allclose, skip_if_no_cuda -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") class TestToNumpyd(unittest.TestCase): - @skipUnless(has_cp, "CuPy is required.") + @skipUnless(HAS_CUPY, "CuPy is required.") def test_cupy_input(self): test_data = cp.array([[1, 2], [3, 4]]) test_data = cp.rot90(test_data) diff --git a/tests/test_to_tensor.py b/tests/test_to_tensor.py index 59097635c1..bfc61cdb19 100644 --- a/tests/test_to_tensor.py +++ b/tests/test_to_tensor.py @@ -15,9 +15,9 @@ from parameterized import parameterized from monai.transforms import ToTensor -from tests.utils import TEST_NDARRAYS, assert_allclose, optional_import +from tests.utils import HAS_CUPY, TEST_NDARRAYS, assert_allclose, optional_import -cp, has_cp = optional_import("cupy") +cp, _ = optional_import("cupy") im = [[1, 2], [3, 4]] @@ -47,7 +47,7 @@ def test_single_input(self, test_data): assert_allclose(result, test_data, type_test=False) self.assertEqual(result.ndim, 0) - @unittest.skipUnless(has_cp, "CuPy is required.") + @unittest.skipUnless(HAS_CUPY, "CuPy is required.") def test_cupy(self): test_data = [[1, 2], [3, 4]] cupy_array = cp.ascontiguousarray(cp.asarray(test_data)) diff --git a/tests/utils.py b/tests/utils.py index af4b7ca4ef..4082cdbdbf 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -214,6 +214,27 @@ def __call__(self, obj): )(obj) +def has_cupy(): + """ + Returns True if the user has installed a version of cupy. + """ + cp, has_cp = optional_import("cupy") + if not has_cp: + return False + try: + x = cp.arange(6, dtype="f").reshape(2, 3) + y = cp.arange(3, dtype="f") + kernel = cp.ElementwiseKernel( + "float32 x, float32 y", "float32 z", """ if (x - 2 > y) { z = x * y; } else { z = x + y; } """, "my_kernel" + ) + return kernel(x, y)[0, 0] == 0 + except Exception: + return False + + +HAS_CUPY = has_cupy() + + def make_nifti_image(array: NdarrayOrTensor, affine=None): """ Create a temporary nifti image on the disk and return the image name. From c332e2ffa1b4f9ff104f77ce8d1738c311410678 Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Thu, 23 Dec 2021 23:36:09 +0000 Subject: [PATCH 2/2] update based on comments Signed-off-by: Wenqi Li --- tests/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils.py b/tests/utils.py index 4082cdbdbf..d56a1ad7a8 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -221,7 +221,7 @@ def has_cupy(): cp, has_cp = optional_import("cupy") if not has_cp: return False - try: + try: # test cupy installation with a basic example x = cp.arange(6, dtype="f").reshape(2, 3) y = cp.arange(3, dtype="f") kernel = cp.ElementwiseKernel(