@@ -229,6 +229,17 @@ def _asarray_from_numpy_ndarray(
229
229
return res
230
230
231
231
232
+ def _is_object_with_buffer_protocol (obj ):
233
+ "Returns True if object support Python buffer protocol"
234
+ try :
235
+ # use context manager to ensure
236
+ # buffer is instantly released
237
+ with memoryview (obj ):
238
+ return True
239
+ except TypeError :
240
+ return False
241
+
242
+
232
243
def asarray (
233
244
obj ,
234
245
dtype = None ,
@@ -238,7 +249,45 @@ def asarray(
238
249
sycl_queue = None ,
239
250
order = "K" ,
240
251
):
241
- """Represents object `obj` as usm_ndarray"""
252
+ """asarray(obj, dtype=None, copy=None, order="K",
253
+ device=None, usm_type=None, sycl_queue=None)
254
+
255
+ Converts `obj` to :class:`dpctl.tensor.usm_ndarray`.
256
+
257
+ Args:
258
+ obj: Python object to convert. Can be an instance of `usm_ndarray`,
259
+ an object representing SYCL USM allocation and implementing
260
+ `__sycl_usm_array_interface__` protocol, an instance
261
+ of `numpy.ndarray`, an object supporting Python buffer protocol,
262
+ a Python scalar, or a (possibly nested) sequence of Python scalars.
263
+ dtype (data type, optional): output array data type. If `dtype` is
264
+ `None`, the output array data type is inferred from data types in
265
+ `obj`. Default: `None`
266
+ copy (`bool`, optional): boolean indicating whether or not to copy the
267
+ input. If `True`, always creates a copy. If `False`, need to copy
268
+ raises `ValueError`. If `None`, try to reuse existing memory
269
+ allocations if possible, but allowed to perform a copy otherwise.
270
+ Default: `None`.
271
+ order ("C","F","A","K", optional): memory layout of the output array.
272
+ Default: "C"
273
+ device (optional): array API concept of device where the output array
274
+ is created. `device` can be `None`, a oneAPI filter selector string,
275
+ an instance of :class:`dpctl.SyclDevice` corresponding to a
276
+ non-partitioned SYCL device, an instance of
277
+ :class:`dpctl.SyclQueue`, or a `Device` object returnedby
278
+ `dpctl.tensor.usm_array.device`. Default: `None`.
279
+ usm_type ("device"|"shared"|"host", optional): The type of SYCL USM
280
+ allocation for the output array. For `usm_type=None` the allocation
281
+ type is inferred from the input if `obj` has USM allocation, or
282
+ `"device"` is used instead. Default: `None`.
283
+ sycl_queue: (:class:`dpctl.SyclQueue`, optional): The SYCL queue to use
284
+ for output array allocation and copying. `sycl_queue` and `device`
285
+ are exclusive keywords, i.e. use one or another. If both are
286
+ specified, a `TypeError` is raised unless both imply the same
287
+ underlying SYCL queue to be used. If both a `None`, the
288
+ `dpctl.SyclQueue()` is used for allocation and copying.
289
+ Default: `None`.
290
+ """
242
291
# 1. Check that copy is a valid keyword
243
292
if copy not in [None , True , False ]:
244
293
raise TypeError (
@@ -313,9 +362,17 @@ def asarray(
313
362
sycl_queue = sycl_queue ,
314
363
order = order ,
315
364
)
316
- elif hasattr (obj , "__dlpack__" ):
317
- raise NotImplementedError (
318
- "Support for __dlpack__ is not yet implemented"
365
+ elif _is_object_with_buffer_protocol (obj ):
366
+ if copy is False :
367
+ raise ValueError (
368
+ f"Converting { type (obj )} to usm_ndarray requires a copy"
369
+ )
370
+ return _asarray_from_numpy_ndarray (
371
+ np .array (obj ),
372
+ dtype = dtype ,
373
+ usm_type = usm_type ,
374
+ sycl_queue = sycl_queue ,
375
+ order = order ,
319
376
)
320
377
elif isinstance (obj , (list , tuple , range )):
321
378
if copy is False :
@@ -335,6 +392,10 @@ def asarray(
335
392
raise NotImplementedError (
336
393
"Converting Python sequences is not implemented"
337
394
)
395
+ if copy is False :
396
+ raise ValueError (
397
+ f"Converting { type (obj )} to usm_ndarray requires a copy"
398
+ )
338
399
# obj is a scalar, create 0d array
339
400
return _asarray_from_numpy_ndarray (
340
401
np .asarray (obj ),
@@ -348,9 +409,35 @@ def asarray(
348
409
def empty (
349
410
sh , dtype = "f8" , order = "C" , device = None , usm_type = "device" , sycl_queue = None
350
411
):
351
- """Creates empty usm_ndarray"""
412
+ """dpctl.tensor.empty(shape, dtype="f8", order="C", device=None,
413
+ usm_type="device", sycl_queue=None)
414
+
415
+ Creates `usm_ndarray` from uninitialized USM allocation.
416
+
417
+ Args:
418
+ shape (tuple): Dimensions of the array to be created.
419
+ dtype (optional): data type of the array. Can be typestring,
420
+ a `numpy.dtype` object, `numpy` char string, or a numpy
421
+ scalar type. Default: "f8"
422
+ order ("C", or F"): memory layout for the array. Default: "C"
423
+ device (optional): array API concept of device where the output array
424
+ is created. `device` can be `None`, a oneAPI filter selector string,
425
+ an instance of :class:`dpctl.SyclDevice` corresponding to a
426
+ non-partitioned SYCL device, an instance of
427
+ :class:`dpctl.SyclQueue`, or a `Device` object returnedby
428
+ `dpctl.tensor.usm_array.device`. Default: `None`.
429
+ usm_type ("device"|"shared"|"host", optional): The type of SYCL USM
430
+ allocation for the output array. Default: `"device"`.
431
+ sycl_queue: (:class:`dpctl.SyclQueue`, optional): The SYCL queue to use
432
+ for output array allocation and copying. `sycl_queue` and `device`
433
+ are exclusive keywords, i.e. use one or another. If both are
434
+ specified, a `TypeError` is raised unless both imply the same
435
+ underlying SYCL queue to be used. If both a `None`, the
436
+ `dpctl.SyclQueue()` is used for allocation and copying.
437
+ Default: `None`.
438
+ """
352
439
dtype = np .dtype (dtype )
353
- if len (order ) == 0 or order [0 ] not in "CcFf" :
440
+ if not isinstance ( order , str ) or len (order ) == 0 or order [0 ] not in "CcFf" :
354
441
raise ValueError (
355
442
"Unrecognized order keyword value, expecting 'F' or 'C'."
356
443
)
0 commit comments