diff --git a/dpctl/_sycl_device_factory.pxd b/dpctl/_sycl_device_factory.pxd index 239d2b398a..88f9d3bc77 100644 --- a/dpctl/_sycl_device_factory.pxd +++ b/dpctl/_sycl_device_factory.pxd @@ -22,10 +22,18 @@ from SYCL standard device_selectors, to get a list of SyclDevices for a specific backend or device_type. """ +from libcpp cimport bool as cpp_bool +from ._sycl_device cimport SyclDevice -cpdef select_accelerator_device() -cpdef select_cpu_device() -cpdef select_default_device() -cpdef select_gpu_device() -cpdef select_host_device() +cpdef SyclDevice select_accelerator_device() +cpdef SyclDevice select_cpu_device() +cpdef SyclDevice select_default_device() +cpdef SyclDevice select_gpu_device() +cpdef SyclDevice select_host_device() cpdef list get_devices(backend=*, device_type=*) +cpdef int get_num_devices(backend=*, device_type=*) +cpdef cpp_bool has_gpu_devices() +cpdef cpp_bool has_cpu_devices() +cpdef cpp_bool has_accelerator_devices() +cpdef cpp_bool has_host_device() + diff --git a/dpctl/_sycl_device_factory.pyx b/dpctl/_sycl_device_factory.pyx index 1b8fbc249a..389553f877 100644 --- a/dpctl/_sycl_device_factory.pyx +++ b/dpctl/_sycl_device_factory.pyx @@ -33,6 +33,7 @@ from ._backend cimport ( DPCTLDefaultSelector_Create, DPCTLDevice_CreateFromSelector, DPCTLDeviceMgr_GetDevices, + DPCTLDeviceMgr_GetNumDevices, DPCTLDeviceSelector_Delete, DPCTLDeviceVectorRef, DPCTLDeviceVector_Delete, @@ -45,7 +46,6 @@ from ._backend cimport ( DPCTLSyclDeviceSelectorRef, DPCTLSyclDeviceType, ) -from ._sycl_device cimport SyclDevice from . import backend_type, device_type as device_type_t __all__ = [ @@ -55,6 +55,11 @@ __all__ = [ "select_default_device", "select_gpu_device", "select_host_device", + "get_num_devices", + "has_cpu_devices", + "has_gpu_devices", + "has_accelerator_devices", + "has_host_device", ] @@ -174,7 +179,65 @@ cpdef list get_devices(backend=backend_type.all, device_type=device_type_t.all): return devices -cpdef select_accelerator_device(): +cpdef int get_num_devices(backend=backend_type.all, device_type=device_type_t.all): + cdef DPCTLSyclBackendType BTy = _backend_type._ALL_BACKENDS + cdef DPCTLSyclDeviceType DTy = _device_type._ALL_DEVICES + cdef int num_devices = 0 + + if isinstance(backend, str): + BTy = _string_to_dpctl_sycl_backend_ty(backend) + elif isinstance(backend, backend_type): + BTy = _enum_to_dpctl_sycl_backend_ty(backend) + else: + raise TypeError( + "backend should be specified as a str or an " + "enum_types.backend_type" + ) + + if isinstance(device_type, str): + DTy = _string_to_dpctl_sycl_device_ty(device_type) + elif isinstance(device_type, device_type_t): + DTy = _enum_to_dpctl_sycl_device_ty(device_type) + else: + raise TypeError( + "device type should be specified as a str or an " + "enum_types.device_type" + ) + + num_devices = DPCTLDeviceMgr_GetNumDevices(BTy | DTy) + + return num_devices + + +cpdef cpp_bool has_cpu_devices(): + """ Returns: True if `sycl::device_type::cpu` devices are present, False otherwise + """ + cdef int num_cpu_dev = DPCTLDeviceMgr_GetNumDevices(_device_type._CPU) + return num_cpu_dev + + +cpdef cpp_bool has_gpu_devices(): + """ Returns: True if `sycl::device_type::gpu` devices are present, False otherwise + """ + cdef int num_gpu_dev = DPCTLDeviceMgr_GetNumDevices(_device_type._GPU) + return num_gpu_dev + + +cpdef cpp_bool has_accelerator_devices(): + """ Returns: True if `sycl::device_type::accelerator` devices are present, False otherwise + """ + cdef int num_accelerator_dev = DPCTLDeviceMgr_GetNumDevices(_device_type._ACCELERATOR) + return num_accelerator_dev + + +cpdef cpp_bool has_host_device(): + """ Returns: True if `sycl::device_type::host` devices are present, False otherwise + """ + cdef int num_host_dev = DPCTLDeviceMgr_GetNumDevices(_device_type._HOST_DEVICE) + return num_host_dev + + +cpdef SyclDevice select_accelerator_device(): """ A wrapper for SYCL's `accelerator_selector` device_selector class. Returns: @@ -194,7 +257,7 @@ cpdef select_accelerator_device(): return Device -cpdef select_cpu_device(): +cpdef SyclDevice select_cpu_device(): """ A wrapper for SYCL's `cpu_selector` device_selector class. Returns: @@ -214,7 +277,7 @@ cpdef select_cpu_device(): return Device -cpdef select_default_device(): +cpdef SyclDevice select_default_device(): """ A wrapper for SYCL's `default_selector` device_selector class. Returns: @@ -234,7 +297,7 @@ cpdef select_default_device(): return Device -cpdef select_gpu_device(): +cpdef SyclDevice select_gpu_device(): """ A wrapper for SYCL's `gpu_selector` device_selector class. Returns: @@ -254,7 +317,7 @@ cpdef select_gpu_device(): return Device -cpdef select_host_device(): +cpdef SyclDevice select_host_device(): """ A wrapper for SYCL's `host_selector` device_selector class. Returns: diff --git a/dpctl/tests/_helper.py b/dpctl/tests/_helper.py new file mode 100644 index 0000000000..c6b2cd2f69 --- /dev/null +++ b/dpctl/tests/_helper.py @@ -0,0 +1,9 @@ +import dpctl + + +def has_gpu(backend="opencl"): + return bool(dpctl.get_num_devices(backend=backend, device_type="gpu")) + + +def has_cpu(backend="opencl"): + return bool(dpctl.get_num_devices(backend=backend, device_type="cpu")) diff --git a/dpctl/tests/test_sycl_kernel_submit.py b/dpctl/tests/test_sycl_kernel_submit.py index 68cadaa858..de05935c5e 100644 --- a/dpctl/tests/test_sycl_kernel_submit.py +++ b/dpctl/tests/test_sycl_kernel_submit.py @@ -23,9 +23,10 @@ import dpctl.memory as dpctl_mem import dpctl.program as dpctl_prog import numpy as np +from ._helper import has_cpu, has_gpu -@unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") +@unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") class Test1DKernelSubmit(unittest.TestCase): def test_create_program_from_source(self): oclSrc = " \ diff --git a/dpctl/tests/test_sycl_program.py b/dpctl/tests/test_sycl_program.py index a5b614a363..330e13d611 100644 --- a/dpctl/tests/test_sycl_program.py +++ b/dpctl/tests/test_sycl_program.py @@ -21,9 +21,10 @@ import dpctl.program as dpctl_prog import unittest import os +from ._helper import has_cpu, has_gpu -@unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") +@unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") class TestProgramFromOCLSource(unittest.TestCase): def test_create_program_from_source(self): oclSrc = " \ @@ -52,7 +53,7 @@ def test_create_program_from_source(self): self.assertEqual(axpyKernel.get_num_args(), 4) -@unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") +@unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") class TestProgramFromSPRIV(unittest.TestCase): def test_create_program_from_spirv(self): @@ -77,7 +78,7 @@ def test_create_program_from_spirv(self): @unittest.skipUnless( - dpctl.has_gpu_queues(backend_ty=dpctl.backend_type.level_zero), + has_gpu(backend=dpctl.backend_type.level_zero), "No Level0 GPU queues available", ) class TestProgramForLevel0GPU(unittest.TestCase): diff --git a/dpctl/tests/test_sycl_queue.py b/dpctl/tests/test_sycl_queue.py index 6d32ec1de8..bd31769cfc 100644 --- a/dpctl/tests/test_sycl_queue.py +++ b/dpctl/tests/test_sycl_queue.py @@ -19,21 +19,26 @@ import dpctl import unittest +from ._helper import has_cpu, has_gpu class TestSyclQueue(unittest.TestCase): - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") - @unittest.skipUnless(dpctl.has_cpu_queues(), "No OpenCL CPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_cpu(), "No OpenCL CPU queues available") def test_queue_not_equals(self): - with dpctl.device_context("opencl:gpu") as gpuQ0: + with dpctl.device_context("opencl:gpu") as gpuQ: + ctx_gpu = gpuQ.get_sycl_context() with dpctl.device_context("opencl:cpu") as cpuQ: - self.assertFalse(cpuQ.equals(gpuQ0)) + ctx_cpu = cpuQ.get_sycl_context() + self.assertFalse(ctx_cpu.equals(ctx_gpu)) - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") def test_queue_equals(self): with dpctl.device_context("opencl:gpu") as gpuQ0: + ctx0 = gpuQ0.get_sycl_context() with dpctl.device_context("opencl:gpu") as gpuQ1: - self.assertTrue(gpuQ0.equals(gpuQ1)) + ctx1 = gpuQ1.get_sycl_context() + self.assertTrue(ctx0.equals(ctx1)) if __name__ == "__main__": diff --git a/dpctl/tests/test_sycl_queue_manager.py b/dpctl/tests/test_sycl_queue_manager.py index 05be7e4ce4..84d10ac015 100644 --- a/dpctl/tests/test_sycl_queue_manager.py +++ b/dpctl/tests/test_sycl_queue_manager.py @@ -19,6 +19,7 @@ import dpctl import unittest +from ._helper import has_cpu, has_gpu class TestGetNumPlatforms(unittest.TestCase): @@ -48,13 +49,13 @@ class TestIsInDeviceContext(unittest.TestCase): def test_is_in_device_context_outside_device_ctxt(self): self.assertFalse(dpctl.is_in_device_context()) - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") def test_is_in_device_context_inside_device_ctxt(self): with dpctl.device_context("opencl:gpu:0"): self.assertTrue(dpctl.is_in_device_context()) - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") - @unittest.skipUnless(dpctl.has_cpu_queues(), "No OpenCL CPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_cpu(), "No OpenCL CPU queues available") def test_is_in_device_context_inside_nested_device_ctxt(self): with dpctl.device_context("opencl:cpu:0"): with dpctl.device_context("opencl:gpu:0"): @@ -76,7 +77,7 @@ def test_get_current_device_type_inside_device_ctxt(self): self.assertNotEqual(dpctl.get_current_device_type(), None) - @unittest.skipUnless(dpctl.has_cpu_queues(), "No OpenCL CPU queues available") + @unittest.skipUnless(has_cpu(), "No OpenCL CPU queues available") def test_get_current_device_type_inside_nested_device_ctxt(self): self.assertNotEqual(dpctl.get_current_device_type(), None) @@ -95,8 +96,8 @@ class TestGetCurrentQueueInMultipleThreads(unittest.TestCase): def test_num_current_queues_outside_with_clause(self): self.assertEqual(dpctl.get_num_activated_queues(), 0) - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") - @unittest.skipUnless(dpctl.has_cpu_queues(), "No OpenCL CPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_cpu(), "No OpenCL CPU queues available") def test_num_current_queues_inside_with_clause(self): with dpctl.device_context("opencl:cpu:0"): self.assertEqual(dpctl.get_num_activated_queues(), 1) @@ -104,8 +105,8 @@ def test_num_current_queues_inside_with_clause(self): self.assertEqual(dpctl.get_num_activated_queues(), 2) self.assertEqual(dpctl.get_num_activated_queues(), 0) - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") - @unittest.skipUnless(dpctl.has_cpu_queues(), "No OpenCL CPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_cpu(), "No OpenCL CPU queues available") def test_num_current_queues_inside_threads(self): from threading import Thread diff --git a/dpctl/tests/test_sycl_usm.py b/dpctl/tests/test_sycl_usm.py index 903c110b76..cd468c5598 100644 --- a/dpctl/tests/test_sycl_usm.py +++ b/dpctl/tests/test_sycl_usm.py @@ -21,6 +21,7 @@ import dpctl from dpctl.memory import MemoryUSMShared, MemoryUSMHost, MemoryUSMDevice import numpy as np +from ._helper import has_cpu, has_gpu class Dummy(MemoryUSMShared): @@ -76,7 +77,7 @@ def test_memory_without_context(self): # Without context self.assertEqual(mobj.get_usm_type(), "shared") - @unittest.skipUnless(dpctl.has_cpu_queues(), "No OpenCL CPU queues available") + @unittest.skipUnless(has_cpu(), "No OpenCL CPU queues available") def test_memory_cpu_context(self): mobj = self._create_memory() @@ -94,7 +95,7 @@ def test_memory_cpu_context(self): # not in the same SYCL context self.assertTrue(usm_type in ["unknown", "shared"]) - @unittest.skipUnless(dpctl.has_gpu_queues(), "No OpenCL GPU queues available") + @unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available") def test_memory_gpu_context(self): mobj = self._create_memory()