Skip to content

Commit fdb3919

Browse files
Merge pull request #575 from IntelPython/coverage_memory
Transition all Python API to use pytest over unittest, improved coverage in dpctl/memory
2 parents 5544129 + ba40dab commit fdb3919

9 files changed

+905
-659
lines changed

dpctl/_sycl_queue_manager.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ cdef class _SyclQueueManager:
7878
Returns:
7979
backend_type: The SYCL backend for the currently selected queue.
8080
"""
81-
return self.get_current_queue().get_sycl_backend()
81+
return self.get_current_queue().backend
8282

8383
cpdef get_current_device_type(self):
8484
"""
@@ -88,7 +88,7 @@ cdef class _SyclQueueManager:
8888
device_type: The SYCL device type for the currently selected queue.
8989
Possible values can be gpu, cpu, accelerator, or host.
9090
"""
91-
return self.get_current_queue().get_sycl_device().device_type
91+
return self.get_current_queue().sycl_device.device_type
9292

9393
cpdef SyclQueue get_current_queue(self):
9494
"""

dpctl/memory/_memory.pyx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ from dpctl._backend cimport ( # noqa: E211
3434
DPCTLaligned_alloc_host,
3535
DPCTLaligned_alloc_shared,
3636
DPCTLContext_Delete,
37+
DPCTLDevice_Copy,
3738
DPCTLEvent_Delete,
3839
DPCTLEvent_Wait,
3940
DPCTLfree_with_queue,
@@ -48,6 +49,7 @@ from dpctl._backend cimport ( # noqa: E211
4849
DPCTLSyclContextRef,
4950
DPCTLSyclDeviceRef,
5051
DPCTLSyclEventRef,
52+
DPCTLSyclQueueRef,
5153
DPCTLSyclUSMRef,
5254
DPCTLUSM_GetPointerDevice,
5355
DPCTLUSM_GetPointerType,
@@ -138,7 +140,7 @@ cdef class _Memory:
138140

139141
cdef _cinit_alloc(self, Py_ssize_t alignment, Py_ssize_t nbytes,
140142
bytes ptr_type, SyclQueue queue):
141-
cdef DPCTLSyclUSMRef p
143+
cdef DPCTLSyclUSMRef p = NULL
142144

143145
self._cinit_empty()
144146

@@ -215,10 +217,12 @@ cdef class _Memory:
215217
)
216218

217219
def __dealloc__(self):
218-
if (self.refobj is None and self.memory_ptr):
219-
DPCTLfree_with_queue(
220-
self.memory_ptr, self.queue.get_queue_ref()
221-
)
220+
if (self.refobj is None):
221+
if self.memory_ptr:
222+
if (type(self.queue) is SyclQueue):
223+
DPCTLfree_with_queue(
224+
self.memory_ptr, self.queue.get_queue_ref()
225+
)
222226
self._cinit_empty()
223227

224228
cdef _getbuffer(self, Py_buffer *buffer, int flags):
@@ -267,7 +271,7 @@ cdef class _Memory:
267271
property _queue:
268272
"""
269273
:class:`dpctl.SyclQueue` with :class:`dpctl.SyclContext` the
270-
USM pointer is bound to and :class:`dpctl.SyclDevice` it was
274+
USM allocation is bound to and :class:`dpctl.SyclDevice` it was
271275
allocated on.
272276
"""
273277
def __get__(self):
@@ -477,8 +481,10 @@ cdef class _Memory:
477481
cdef DPCTLSyclDeviceRef dref = DPCTLUSM_GetPointerDevice(
478482
p, ctx.get_context_ref()
479483
)
480-
481-
return SyclDevice._create(dref)
484+
cdef DPCTLSyclDeviceRef dref_copy = DPCTLDevice_Copy(dref)
485+
if (dref_copy is NULL):
486+
raise RuntimeError("Could not create a copy of sycl device")
487+
return SyclDevice._create(dref_copy) # deletes the argument
482488

483489
@staticmethod
484490
cdef bytes get_pointer_type(DPCTLSyclUSMRef p, SyclContext ctx):

dpctl/memory/_sycl_usm_array_interface_utils.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ cdef DPCTLSyclQueueRef get_queue_ref_from_ptr_and_syclobj(
5454
if pycapsule.PyCapsule_IsValid(cap, "SyclQueueRef"):
5555
q = SyclQueue(cap)
5656
return _queue_ref_copy_from_SyclQueue(ptr, <SyclQueue> q)
57-
elif pycapsule.PyCapsule_IsValid(cap, "SyclContexRef"):
57+
elif pycapsule.PyCapsule_IsValid(cap, "SyclContextRef"):
5858
ctx = <SyclContext>SyclContext(cap)
5959
return _queue_ref_copy_from_USMRef_and_SyclContext(ptr, ctx)
6060
else:

dpctl/tests/test_dparray.py

Lines changed: 79 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,85 +17,104 @@
1717
"""Unit test cases for dpctl.tensor.numpy_usm_shared.
1818
"""
1919

20-
import unittest
21-
2220
import numpy
2321

2422
from dpctl.tensor import numpy_usm_shared as dparray
2523

2624

27-
class Test_dparray(unittest.TestCase):
28-
def setUp(self):
29-
self.X = dparray.ndarray((256, 4), dtype="d")
30-
self.X.fill(1.0)
25+
def get_arg():
26+
X = dparray.ndarray((256, 4), dtype="d")
27+
X.fill(1.0)
28+
return X
29+
30+
31+
def test_dparray_type():
32+
X = get_arg()
33+
assert isinstance(X, dparray.ndarray)
34+
35+
36+
def test_dparray_as_ndarray_self():
37+
X = get_arg()
38+
Y = X.as_ndarray()
39+
assert type(Y) == numpy.ndarray
40+
41+
42+
def test_dparray_as_ndarray():
43+
X = get_arg()
44+
Y = dparray.as_ndarray(X)
45+
assert type(Y) == numpy.ndarray
46+
47+
48+
def test_dparray_from_ndarray():
49+
X = get_arg()
50+
Y = dparray.as_ndarray(X)
51+
dp1 = dparray.from_ndarray(Y)
52+
assert isinstance(dp1, dparray.ndarray)
53+
54+
55+
def test_multiplication_dparray():
56+
C = get_arg() * 5
57+
assert isinstance(C, dparray.ndarray)
58+
59+
60+
def test_inplace_sub():
61+
X = get_arg()
62+
X -= 1
3163

32-
def test_dparray_type(self):
33-
self.assertIsInstance(self.X, dparray.ndarray)
3464

35-
def test_dparray_as_ndarray_self(self):
36-
Y = self.X.as_ndarray()
37-
self.assertEqual(type(Y), numpy.ndarray)
65+
def test_dparray_through_python_func():
66+
def func_operation_with_const(dpctl_array):
67+
return dpctl_array * 2.0 + 13
3868

39-
def test_dparray_as_ndarray(self):
40-
Y = dparray.as_ndarray(self.X)
41-
self.assertEqual(type(Y), numpy.ndarray)
69+
C = get_arg() * 5
70+
dp_func = func_operation_with_const(C)
71+
assert isinstance(dp_func, dparray.ndarray)
4272

43-
def test_dparray_from_ndarray(self):
44-
Y = dparray.as_ndarray(self.X)
45-
dp1 = dparray.from_ndarray(Y)
46-
self.assertIsInstance(dp1, dparray.ndarray)
4773

48-
def test_multiplication_dparray(self):
49-
C = self.X * 5
50-
self.assertIsInstance(C, dparray.ndarray)
74+
def test_dparray_mixing_dpctl_and_numpy():
75+
dp_numpy = numpy.ones((256, 4), dtype="d")
76+
X = get_arg()
77+
res = dp_numpy * X
78+
assert isinstance(X, dparray.ndarray)
79+
assert isinstance(res, dparray.ndarray)
5180

52-
def test_inplace_sub(self):
53-
self.X -= 1
5481

55-
def test_dparray_through_python_func(self):
56-
def func_operation_with_const(dpctl_array):
57-
return dpctl_array * 2.0 + 13
82+
def test_dparray_shape():
83+
X = get_arg()
84+
res = X.shape
85+
assert res == (256, 4)
5886

59-
C = self.X * 5
60-
dp_func = func_operation_with_const(C)
61-
self.assertIsInstance(dp_func, dparray.ndarray)
6287

63-
def test_dparray_mixing_dpctl_and_numpy(self):
64-
dp_numpy = numpy.ones((256, 4), dtype="d")
65-
res = dp_numpy * self.X
66-
self.assertIsInstance(self.X, dparray.ndarray)
67-
self.assertIsInstance(res, dparray.ndarray)
88+
def test_dparray_T():
89+
X = get_arg()
90+
res = X.T
91+
assert res.shape == (4, 256)
6892

69-
def test_dparray_shape(self):
70-
res = self.X.shape
71-
self.assertEqual(res, (256, 4))
7293

73-
def test_dparray_T(self):
74-
res = self.X.T
75-
self.assertEqual(res.shape, (4, 256))
94+
def test_numpy_ravel_with_dparray():
95+
X = get_arg()
96+
res = numpy.ravel(X)
97+
assert res.shape == (1024,)
7698

77-
def test_numpy_ravel_with_dparray(self):
78-
res = numpy.ravel(self.X)
79-
self.assertEqual(res.shape, (1024,))
8099

81-
def test_numpy_sum_with_dparray(self):
82-
res = numpy.sum(self.X)
83-
self.assertEqual(res, 1024.0)
100+
def test_numpy_sum_with_dparray():
101+
X = get_arg()
102+
res = numpy.sum(X)
103+
assert res == 1024.0
84104

85-
def test_numpy_sum_with_dparray_out(self):
86-
res = dparray.empty((self.X.shape[1],), dtype=self.X.dtype)
87-
res2 = numpy.sum(self.X, axis=0, out=res)
88-
self.assertTrue(res is res2)
89-
self.assertIsInstance(res2, dparray.ndarray)
90105

91-
def test_frexp_with_out(self):
92-
X = dparray.array([0.5, 4.7])
93-
mant = dparray.empty((2,), dtype="d")
94-
exp = dparray.empty((2,), dtype="i4")
95-
res = numpy.frexp(X, out=(mant, exp))
96-
self.assertTrue(res[0] is mant)
97-
self.assertTrue(res[1] is exp)
106+
def test_numpy_sum_with_dparray_out():
107+
X = get_arg()
108+
res = dparray.empty((X.shape[1],), dtype=X.dtype)
109+
res2 = numpy.sum(X, axis=0, out=res)
110+
assert res is res2
111+
assert isinstance(res2, dparray.ndarray)
98112

99113

100-
if __name__ == "__main__":
101-
unittest.main()
114+
def test_frexp_with_out():
115+
X = dparray.array([0.5, 4.7])
116+
mant = dparray.empty((2,), dtype="d")
117+
exp = dparray.empty((2,), dtype="i4")
118+
res = numpy.frexp(X, out=(mant, exp))
119+
assert res[0] is mant
120+
assert res[1] is exp

dpctl/tests/test_sycl_kernel_submit.py

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,60 +18,55 @@
1818
"""
1919

2020
import ctypes
21-
import unittest
2221

2322
import numpy as np
23+
import pytest
2424

2525
import dpctl
2626
import dpctl.memory as dpctl_mem
2727
import dpctl.program as dpctl_prog
2828

29-
from ._helper import has_gpu
3029

30+
def test_create_program_from_source():
31+
try:
32+
q = dpctl.SyclQueue("opencl", property="enable_profiling")
33+
except dpctl.SyclQueueCreationError:
34+
pytest.skip("OpenCL queue could not be created")
35+
oclSrc = " \
36+
kernel void axpy(global int* a, global int* b, global int* c, int d) { \
37+
size_t index = get_global_id(0); \
38+
c[index] = d*a[index] + b[index]; \
39+
}"
40+
prog = dpctl_prog.create_program_from_source(q, oclSrc)
41+
axpyKernel = prog.get_sycl_kernel("axpy")
3142

32-
@unittest.skipUnless(has_gpu(), "No OpenCL GPU queues available")
33-
class Test1DKernelSubmit(unittest.TestCase):
34-
def test_create_program_from_source(self):
35-
oclSrc = " \
36-
kernel void axpy(global int* a, global int* b, global int* c, int d) { \
37-
size_t index = get_global_id(0); \
38-
c[index] = d*a[index] + b[index]; \
39-
}"
40-
q = dpctl.SyclQueue("opencl:gpu", property="enable_profiling")
41-
prog = dpctl_prog.create_program_from_source(q, oclSrc)
42-
axpyKernel = prog.get_sycl_kernel("axpy")
43+
n_elems = 1024 * 512
44+
bufBytes = n_elems * np.dtype("i").itemsize
45+
abuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
46+
bbuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
47+
cbuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
48+
a = np.ndarray((n_elems,), buffer=abuf, dtype="i")
49+
b = np.ndarray((n_elems,), buffer=bbuf, dtype="i")
50+
c = np.ndarray((n_elems,), buffer=cbuf, dtype="i")
51+
a[:] = np.arange(n_elems)
52+
b[:] = np.arange(n_elems, 0, -1)
53+
c[:] = 0
54+
d = 2
55+
args = []
4356

44-
n_elems = 1024 * 512
45-
bufBytes = n_elems * np.dtype("i").itemsize
46-
abuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
47-
bbuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
48-
cbuf = dpctl_mem.MemoryUSMShared(bufBytes, queue=q)
49-
a = np.ndarray((n_elems,), buffer=abuf, dtype="i")
50-
b = np.ndarray((n_elems,), buffer=bbuf, dtype="i")
51-
c = np.ndarray((n_elems,), buffer=cbuf, dtype="i")
52-
a[:] = np.arange(n_elems)
53-
b[:] = np.arange(n_elems, 0, -1)
54-
c[:] = 0
55-
d = 2
56-
args = []
57+
args.append(a.base)
58+
args.append(b.base)
59+
args.append(c.base)
60+
args.append(ctypes.c_int(d))
5761

58-
args.append(a.base)
59-
args.append(b.base)
60-
args.append(c.base)
61-
args.append(ctypes.c_int(d))
62+
r = [
63+
n_elems,
64+
]
6265

63-
r = [
64-
n_elems,
65-
]
66-
67-
timer = dpctl.SyclTimer()
68-
with timer(q):
69-
q.submit(axpyKernel, args, r)
70-
ref_c = a * d + b
71-
host_dt, device_dt = timer.dt
72-
self.assertTrue(host_dt > device_dt)
73-
self.assertTrue(np.allclose(c, ref_c))
74-
75-
76-
if __name__ == "__main__":
77-
unittest.main()
66+
timer = dpctl.SyclTimer()
67+
with timer(q):
68+
q.submit(axpyKernel, args, r)
69+
ref_c = a * d + b
70+
host_dt, device_dt = timer.dt
71+
assert host_dt > device_dt
72+
assert np.allclose(c, ref_c)

0 commit comments

Comments
 (0)