Skip to content

Commit 4028c85

Browse files
Merge pull request #1067 from IntelPython/feature/usm-ndarray-ctor-capi
Extended UsmNDArray creation C-API
2 parents 6308866 + c0feeef commit 4028c85

File tree

4 files changed

+269
-31
lines changed

4 files changed

+269
-31
lines changed

dpctl/apis/include/dpctl4pybind11.hpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,16 +115,24 @@ class dpctl_capi
115115
DPCTLSyclQueueRef (*UsmNDArray_GetQueueRef_)(PyUSMArrayObject *);
116116
py::ssize_t (*UsmNDArray_GetOffset_)(PyUSMArrayObject *);
117117
void (*UsmNDArray_SetWritableFlag_)(PyUSMArrayObject *, int);
118-
PyObject *(*UsmNDArray_MakeFromMemory_)(int,
119-
const py::ssize_t *,
120-
int,
121-
Py_MemoryObject *,
122-
py::ssize_t,
123-
char);
124-
PyObject *(*UsmNDArray_MakeFromPtr_)(size_t,
118+
PyObject *(*UsmNDArray_MakeSimpleFromMemory_)(int,
119+
const py::ssize_t *,
120+
int,
121+
Py_MemoryObject *,
122+
py::ssize_t,
123+
char);
124+
PyObject *(*UsmNDArray_MakeSimpleFromPtr_)(size_t,
125+
int,
126+
DPCTLSyclUSMRef,
127+
DPCTLSyclQueueRef,
128+
PyObject *);
129+
PyObject *(*UsmNDArray_MakeFromPtr_)(int,
130+
const py::ssize_t *,
125131
int,
132+
const py::ssize_t *,
126133
DPCTLSyclUSMRef,
127134
DPCTLSyclQueueRef,
135+
py::ssize_t,
128136
PyObject *);
129137

130138
int USM_ARRAY_C_CONTIGUOUS_;
@@ -233,12 +241,13 @@ class dpctl_capi
233241
UsmNDArray_GetTypenum_(nullptr), UsmNDArray_GetElementSize_(nullptr),
234242
UsmNDArray_GetFlags_(nullptr), UsmNDArray_GetQueueRef_(nullptr),
235243
UsmNDArray_GetOffset_(nullptr), UsmNDArray_SetWritableFlag_(nullptr),
236-
UsmNDArray_MakeFromMemory_(nullptr), UsmNDArray_MakeFromPtr_(nullptr),
237-
USM_ARRAY_C_CONTIGUOUS_(0), USM_ARRAY_F_CONTIGUOUS_(0),
238-
USM_ARRAY_WRITABLE_(0), UAR_BOOL_(-1), UAR_SHORT_(-1),
239-
UAR_USHORT_(-1), UAR_INT_(-1), UAR_UINT_(-1), UAR_LONG_(-1),
240-
UAR_ULONG_(-1), UAR_LONGLONG_(-1), UAR_ULONGLONG_(-1), UAR_FLOAT_(-1),
241-
UAR_DOUBLE_(-1), UAR_CFLOAT_(-1), UAR_CDOUBLE_(-1),
244+
UsmNDArray_MakeSimpleFromMemory_(nullptr),
245+
UsmNDArray_MakeSimpleFromPtr_(nullptr),
246+
UsmNDArray_MakeFromPtr_(nullptr), USM_ARRAY_C_CONTIGUOUS_(0),
247+
USM_ARRAY_F_CONTIGUOUS_(0), USM_ARRAY_WRITABLE_(0), UAR_BOOL_(-1),
248+
UAR_SHORT_(-1), UAR_USHORT_(-1), UAR_INT_(-1), UAR_UINT_(-1),
249+
UAR_LONG_(-1), UAR_ULONG_(-1), UAR_LONGLONG_(-1), UAR_ULONGLONG_(-1),
250+
UAR_FLOAT_(-1), UAR_DOUBLE_(-1), UAR_CFLOAT_(-1), UAR_CDOUBLE_(-1),
242251
UAR_TYPE_SENTINEL_(-1), UAR_HALF_(-1), UAR_INT8_(-1), UAR_UINT8_(-1),
243252
UAR_INT16_(-1), UAR_UINT16_(-1), UAR_INT32_(-1), UAR_UINT32_(-1),
244253
UAR_INT64_(-1), UAR_UINT64_(-1), default_sycl_queue_{},
@@ -310,7 +319,9 @@ class dpctl_capi
310319
this->UsmNDArray_GetQueueRef_ = UsmNDArray_GetQueueRef;
311320
this->UsmNDArray_GetOffset_ = UsmNDArray_GetOffset;
312321
this->UsmNDArray_SetWritableFlag_ = UsmNDArray_SetWritableFlag;
313-
this->UsmNDArray_MakeFromMemory_ = UsmNDArray_MakeFromMemory;
322+
this->UsmNDArray_MakeSimpleFromMemory_ =
323+
UsmNDArray_MakeSimpleFromMemory;
324+
this->UsmNDArray_MakeSimpleFromPtr_ = UsmNDArray_MakeSimpleFromPtr;
314325
this->UsmNDArray_MakeFromPtr_ = UsmNDArray_MakeFromPtr;
315326

316327
// constants

dpctl/tensor/_stride_utils.pxi

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ cdef int _from_input_shape_strides(
141141
str_i = <Py_ssize_t> strides[i]
142142
strides_arr[i] = str_i
143143
if str_i > 0:
144-
max_shift += strides_arr[i] * (shape_arr[i] - 1)
144+
max_shift += str_i * (shape_arr[i] - 1)
145145
else:
146-
min_shift += strides_arr[i] * (shape_arr[i] - 1)
146+
min_shift += str_i * (shape_arr[i] - 1)
147147
min_disp[0] = min_shift
148148
max_disp[0] = max_shift
149149
if max_shift == min_shift + (elem_count - 1):
@@ -199,7 +199,7 @@ cdef int _from_input_shape_strides(
199199
# return ERROR_INTERNAL
200200

201201

202-
cdef object _make_int_tuple(int nd, Py_ssize_t *ary):
202+
cdef object _make_int_tuple(int nd, const Py_ssize_t *ary):
203203
"""
204204
Makes Python tuple from C array
205205
"""
@@ -216,7 +216,7 @@ cdef object _make_int_tuple(int nd, Py_ssize_t *ary):
216216
return None
217217

218218

219-
cdef object _make_reversed_int_tuple(int nd, Py_ssize_t *ary):
219+
cdef object _make_reversed_int_tuple(int nd, const Py_ssize_t *ary):
220220
"""
221221
Makes Python reversed tuple from C array
222222
"""

dpctl/tensor/_usmarray.pyx

Lines changed: 136 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ cdef class usm_ndarray:
351351
return mem.queue
352352

353353
cdef c_dpctl.DPCTLSyclQueueRef get_queue_ref(self) except *:
354+
"""
355+
Returns a copy of DPCTLSyclQueueRef associated with array
356+
"""
354357
cdef c_dpctl.SyclQueue q = self.get_sycl_queue()
355358
cdef c_dpctl.DPCTLSyclQueueRef QRef = q.get_queue_ref()
356359
cdef c_dpctl.DPCTLSyclQueueRef QRefCopy = NULL
@@ -1316,15 +1319,24 @@ cdef api void UsmNDArray_SetWritableFlag(usm_ndarray arr, int flag):
13161319
arr_fl |= (USM_ARRAY_WRITABLE if flag else 0)
13171320
arr.flags_ = arr_fl
13181321

1319-
cdef api object UsmNDArray_MakeFromMemory(
1322+
cdef api object UsmNDArray_MakeSimpleFromMemory(
13201323
int nd, const Py_ssize_t *shape, int typenum,
13211324
c_dpmem._Memory mobj, Py_ssize_t offset, char order
13221325
):
1323-
"""Create usm_ndarray.
1324-
1325-
Equivalent to usm_ndarray(
1326-
_make_tuple(nd, shape), dtype=_make_dtype(typenum),
1327-
buffer=mobj, offset=offset)
1326+
"""Create contiguous usm_ndarray.
1327+
1328+
Args:
1329+
nd: number of dimensions (non-negative)
1330+
shape: array of nd non-negative array's sizes along each dimension
1331+
typenum: array elemental type number
1332+
ptr: pointer to the start of allocation
1333+
QRef: DPCTLSyclQueueRef associated with the allocation
1334+
offset: distance between element with zero multi-index and the
1335+
start of allocation
1336+
oder: Memory layout of the array. Use 'C' for C-contiguous or
1337+
row-major layout; 'F' for F-contiguous or column-major layout
1338+
Returns:
1339+
Created usm_ndarray instance
13281340
"""
13291341
cdef object shape_tuple = _make_int_tuple(nd, <Py_ssize_t *>shape)
13301342
cdef usm_ndarray arr = usm_ndarray(
@@ -1337,17 +1349,25 @@ cdef api object UsmNDArray_MakeFromMemory(
13371349
return arr
13381350

13391351

1340-
cdef api object UsmNDArray_MakeFromPtr(
1352+
cdef api object UsmNDArray_MakeSimpleFromPtr(
13411353
size_t nelems,
13421354
int typenum,
13431355
c_dpctl.DPCTLSyclUSMRef ptr,
13441356
c_dpctl.DPCTLSyclQueueRef QRef,
13451357
object owner
13461358
):
1347-
"""Create usm_ndarray from pointer.
1348-
1349-
Argument owner=None implies transert of USM allocation ownership
1350-
to create array object.
1359+
"""Create 1D contiguous usm_ndarray from pointer.
1360+
1361+
Args:
1362+
nelems: number of elements in array
1363+
typenum: array elemental type number
1364+
ptr: pointer to the start of allocation
1365+
QRef: DPCTLSyclQueueRef associated with the allocation
1366+
owner: Python object managing lifetime of USM allocation.
1367+
Value None implies transfer of USM allocation ownership
1368+
to the created array object.
1369+
Returns:
1370+
Created usm_ndarray instance
13511371
"""
13521372
cdef size_t itemsize = type_bytesize(typenum)
13531373
cdef size_t nbytes = itemsize * nelems
@@ -1360,3 +1380,108 @@ cdef api object UsmNDArray_MakeFromPtr(
13601380
buffer=mobj
13611381
)
13621382
return arr
1383+
1384+
cdef api object UsmNDArray_MakeFromPtr(
1385+
int nd,
1386+
const Py_ssize_t *shape,
1387+
int typenum,
1388+
const Py_ssize_t *strides,
1389+
c_dpctl.DPCTLSyclUSMRef ptr,
1390+
c_dpctl.DPCTLSyclQueueRef QRef,
1391+
Py_ssize_t offset,
1392+
object owner
1393+
):
1394+
"""
1395+
General usm_ndarray constructor from externally made USM-allocation.
1396+
1397+
Args:
1398+
nd: number of dimensions (non-negative)
1399+
shape: array of nd non-negative array's sizes along each dimension
1400+
typenum: array elemental type number
1401+
strides: array of nd strides along each dimension in elements
1402+
ptr: pointer to the start of allocation
1403+
QRef: DPCTLSyclQueueRef associated with the allocation
1404+
offset: distance between element with zero multi-index and the
1405+
start of allocation
1406+
owner: Python object managing lifetime of USM allocation.
1407+
Value None implies transfer of USM allocation ownership
1408+
to the created array object.
1409+
Returns:
1410+
Created usm_ndarray instance
1411+
"""
1412+
cdef size_t itemsize = type_bytesize(typenum)
1413+
cdef int err = 0
1414+
cdef size_t nelems = 1
1415+
cdef Py_ssize_t min_disp = 0
1416+
cdef Py_ssize_t max_disp = 0
1417+
cdef Py_ssize_t step_ = 0
1418+
cdef Py_ssize_t dim_ = 0
1419+
cdef it = 0
1420+
cdef c_dpmem._Memory mobj
1421+
cdef usm_ndarray arr
1422+
cdef object obj_shape
1423+
cdef object obj_strides
1424+
1425+
if (nd < 0):
1426+
raise ValueError("Dimensionality must be non-negative")
1427+
if (ptr is NULL or QRef is NULL):
1428+
raise ValueError(
1429+
"Non-null USM allocation pointer and QRef are expected"
1430+
)
1431+
if (nd == 0):
1432+
# case of 0d scalars
1433+
mobj = c_dpmem._Memory.create_from_usm_pointer_size_qref(
1434+
ptr, itemsize, QRef, memory_owner=owner
1435+
)
1436+
arr = usm_ndarray(
1437+
tuple(),
1438+
dtype=_make_typestr(typenum),
1439+
buffer=mobj
1440+
)
1441+
return arr
1442+
if (shape is NULL or strides is NULL):
1443+
raise ValueError("Both shape and stride vectors are required")
1444+
for it in range(nd):
1445+
dim_ = shape[it]
1446+
if dim_ < 0:
1447+
raise ValueError(
1448+
f"Dimension along axis {it} must be non-negative"
1449+
)
1450+
nelems *= dim_
1451+
if dim_ > 0:
1452+
step_ = strides[it]
1453+
if step_ > 0:
1454+
max_disp += step_ * (dim_ - 1)
1455+
else:
1456+
min_disp += step_ * (dim_ - 1)
1457+
1458+
obj_shape = _make_int_tuple(nd, shape)
1459+
obj_strides = _make_int_tuple(nd, strides)
1460+
if nelems == 0:
1461+
mobj = c_dpmem._Memory.create_from_usm_pointer_size_qref(
1462+
ptr, itemsize, QRef, memory_owner=owner
1463+
)
1464+
arr = usm_ndarray(
1465+
obj_shape,
1466+
dtype=_make_typestr(typenum),
1467+
strides=obj_strides,
1468+
buffer=mobj,
1469+
offset=0
1470+
)
1471+
return arr
1472+
if offset + min_disp < 0:
1473+
raise ValueError(
1474+
"Given shape, strides and offset reference out-of-bound memory"
1475+
)
1476+
nbytes = itemsize * (offset + max_disp + 1)
1477+
mobj = c_dpmem._Memory.create_from_usm_pointer_size_qref(
1478+
ptr, nbytes, QRef, memory_owner=owner
1479+
)
1480+
arr = usm_ndarray(
1481+
obj_shape,
1482+
dtype=_make_typestr(typenum),
1483+
strides=obj_strides,
1484+
buffer=mobj,
1485+
offset=offset
1486+
)
1487+
return arr

0 commit comments

Comments
 (0)