diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 05623fc67a0a..2b779f57b142 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # ***************************************************************************** -# Copyright (c) 2016-2020, Intel Corporation +# Copyright (c) 2016-2022, Intel Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,10 +25,9 @@ # ***************************************************************************** import dpctl.tensor as dpt -from dpctl.tensor._device import normalize_queue_device -import dpnp import numpy +import dpnp class dpnp_array: """ @@ -64,7 +63,7 @@ def __init__(self, copy=False, order=order) else: - sycl_queue_normalized = normalize_queue_device(sycl_queue=sycl_queue, device=device) + sycl_queue_normalized = dpnp.get_normalized_queue_device(sycl_queue=sycl_queue, device=device) self._array_obj = dpt.usm_ndarray(shape, dtype=dtype, strides=strides, diff --git a/dpnp/dpnp_container.py b/dpnp/dpnp_container.py index bfc7e469d700..b4b134f9dc54 100644 --- a/dpnp/dpnp_container.py +++ b/dpnp/dpnp_container.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # ***************************************************************************** -# Copyright (c) 2016-2020, Intel Corporation +# Copyright (c) 2016-2022, Intel Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,28 +34,10 @@ """ -import dpnp.config as config -# from dpnp.dparray import dparray -from dpnp.dpnp_array import dpnp_array - -import numpy - import dpctl.tensor as dpt -from dpctl.tensor._device import normalize_queue_device - -if config.__DPNP_OUTPUT_DPCTL__: - try: - """ - Detect DPCtl availability to use data container - """ - import dpctl.tensor as dpctl - - except ImportError: - """ - No DPCtl data container available - """ - config.__DPNP_OUTPUT_DPCTL__ = 0 +from dpnp.dpnp_array import dpnp_array +import dpnp __all__ = [ @@ -77,14 +59,15 @@ def asarray(x1, else: x1_obj = x1 - sycl_queue_normalized = normalize_queue_device(sycl_queue=sycl_queue, device=device) + sycl_queue_normalized = dpnp.get_normalized_queue_device(x1_obj, sycl_queue=sycl_queue, device=device) + + """Converts incoming 'x1' object to 'dpnp_array'.""" array_obj = dpt.asarray(x1_obj, dtype=dtype, copy=copy, order=order, usm_type=usm_type, sycl_queue=sycl_queue_normalized) - return dpnp_array(array_obj.shape, buffer=array_obj, order=order) @@ -94,13 +77,12 @@ def empty(shape, device=None, usm_type="device", sycl_queue=None): - """Creates `dpnp_array` from uninitialized USM allocation.""" - sycl_queue_normalized = normalize_queue_device(sycl_queue=sycl_queue, device=device) + sycl_queue_normalized = dpnp.get_normalized_queue_device(sycl_queue=sycl_queue, device=device) + """Creates `dpnp_array` from uninitialized USM allocation.""" array_obj = dpt.empty(shape, dtype=dtype, order=order, usm_type=usm_type, sycl_queue=sycl_queue_normalized) - return dpnp_array(array_obj.shape, buffer=array_obj, order=order) diff --git a/dpnp/dpnp_iface.py b/dpnp/dpnp_iface.py index d0fccd6fcaed..5aa69ced4aec 100644 --- a/dpnp/dpnp_iface.py +++ b/dpnp/dpnp_iface.py @@ -2,7 +2,7 @@ # distutils: language = c++ # -*- coding: utf-8 -*- # ***************************************************************************** -# Copyright (c) 2016-2020, Intel Corporation +# Copyright (c) 2016-2022, Intel Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -47,6 +47,7 @@ import collections import dpctl +import dpctl.tensor as dpt from dpnp.dpnp_algo import * from dpnp.dpnp_utils import * @@ -62,7 +63,8 @@ "dpnp_queue_initialize", "dpnp_queue_is_cpu", "get_dpnp_descriptor", - "get_include" + "get_include", + "get_normalized_queue_device" ] from dpnp.dpnp_iface_arraycreation import * @@ -248,3 +250,50 @@ def get_include(): dpnp_path = os.path.join(os.path.dirname(__file__), "backend", "include") return dpnp_path + + +def get_normalized_queue_device(obj=None, + device=None, + sycl_queue=None): + """ + Utility to process complementary keyword arguments 'device' and 'sycl_queue' + in subsequent calls of functions from `dpctl.tensor` module. + + If both arguments 'device' and 'sycl_queue' have default value `None` + and 'obj' has `sycl_queue` attribute, it assumes that Compute Follows Data + approach has to be applied and so the resulting SYCL queue will be normalized + based on the queue value from 'obj'. + + Args: + obj (optional): A python object. Can be an instance of `dpnp_array`, + `dpctl.tensor.usm_ndarray`, an object representing SYCL USM allocation + and implementing `__sycl_usm_array_interface__` protocol, + an instance of `numpy.ndarray`, an object supporting Python buffer protocol, + a Python scalar, or a (possibly nested) sequence of Python scalars. + sycl_queue (:class:`dpctl.SyclQueue`, optional): + explicitly indicates where USM allocation is done + and the population code (if any) is executed. + Value `None` is interpreted as get the SYCL queue + from `obj` parameter if not None, from `device` keyword, + or use default queue. + Default: None + device (string, :class:`dpctl.SyclDevice`, :class:`dpctl.SyclQueue, + :class:`dpctl.tensor.Device`, optional): + array-API keyword indicating non-partitioned SYCL device + where array is allocated. + Returns + :class:`dpctl.SyclQueue` object normalized by `normalize_queue_device` call + of `dpctl.tensor` module invoked with 'device' and 'sycl_queue' values. + If both incoming 'device' and 'sycl_queue' are None and 'obj' has `sycl_queue` attribute, + the normalization will be performed for 'obj.sycl_queue' value. + Raises: + TypeError: if argument is not of the expected type, or keywords + imply incompatible queues. + """ + if device is None and sycl_queue is None and obj is not None and hasattr(obj, 'sycl_queue'): + sycl_queue = obj.sycl_queue + + # TODO: remove check dpt._device has attribute 'normalize_queue_device' + if hasattr(dpt._device, 'normalize_queue_device'): + return dpt._device.normalize_queue_device(sycl_queue=sycl_queue, device=device) + return sycl_queue diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index b858db48a1fa..1f625d408014 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -319,3 +319,26 @@ def test_to_device(device_from, device_to): y = x.to_device(device_to) assert y.get_array().sycl_device == device_to + + +@pytest.mark.parametrize("device", + valid_devices, + ids=[device.filter_string for device in valid_devices]) +@pytest.mark.parametrize("func", + ["array", "asarray"]) +@pytest.mark.parametrize("device_param", + ["", "None", "sycl_device"], + ids=['Empty', 'None', "device"]) +@pytest.mark.parametrize("queue_param", + ["", "None", "sycl_queue"], + ids=['Empty', 'None', "queue"]) +def test_array_copy(device, func, device_param, queue_param): + data = numpy.ones(100) + dpnp_data = getattr(dpnp, func)(data, device=device) + + kwargs_items = {'device': device_param, 'sycl_queue': queue_param}.items() + kwargs = {k: getattr(dpnp_data, v, None) for k,v in kwargs_items if v != ""} + + result = dpnp.array(dpnp_data, **kwargs) + + assert_sycl_queue_equal(result.sycl_queue, dpnp_data.sycl_queue)