Skip to content

Align normalize_queue_device call with CFD #1200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions dpnp/dpnp_array.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
"""
Expand Down Expand Up @@ -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,
Expand Down
34 changes: 8 additions & 26 deletions dpnp/dpnp_container.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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__ = [
Expand 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)


Expand All @@ -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)
53 changes: 51 additions & 2 deletions dpnp/dpnp_iface.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -47,6 +47,7 @@
import collections

import dpctl
import dpctl.tensor as dpt

from dpnp.dpnp_algo import *
from dpnp.dpnp_utils import *
Expand All @@ -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 *
Expand Down Expand Up @@ -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
23 changes: 23 additions & 0 deletions tests/test_sycl_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)