diff --git a/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp b/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp index 63b6195e7889..eafa50d4cee2 100644 --- a/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp @@ -1,5 +1,5 @@ //***************************************************************************** -// 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 @@ -183,6 +183,7 @@ where, \ dep_event_vec_ref); \ DPCTLEvent_WaitAndThrow(event_ref); \ + DPCTLEvent_Delete(event_ref); \ } \ \ template \ @@ -690,6 +691,7 @@ static void func_map_init_elemwise_1arg_2type(func_map_t& fmap) where, \ dep_event_vec_ref); \ DPCTLEvent_WaitAndThrow(event_ref); \ + DPCTLEvent_Delete(event_ref); \ } \ \ template \ @@ -1067,6 +1069,7 @@ static void func_map_init_elemwise_1arg_1type(func_map_t& fmap) dep_event_vec_ref \ ); \ DPCTLEvent_WaitAndThrow(event_ref); \ + DPCTLEvent_Delete(event_ref); \ } \ \ template \ @@ -1732,6 +1735,11 @@ static void func_map_init_elemwise_2arg_3type(func_map_t& fmap) eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_BLN][eft_DBL] = { eft_DBL, (void*)dpnp_multiply_c_ext}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_BLN][eft_C64] = { + eft_C64, (void*)dpnp_multiply_c_ext, bool, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_BLN][eft_C128] = { + eft_C128, (void*)dpnp_multiply_c_ext, bool, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_BLN] = { eft_INT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_INT] = { @@ -1739,9 +1747,14 @@ static void func_map_init_elemwise_2arg_3type(func_map_t& fmap) fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_LNG] = { eft_LNG, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_FLT] = { - eft_DBL, (void*)dpnp_multiply_c_ext}; + eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_DBL] = { eft_DBL, (void*)dpnp_multiply_c_ext}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_C64] = { + eft_C64, (void*)dpnp_multiply_c_ext, int32_t, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_INT][eft_C128] = { + eft_C128, (void*)dpnp_multiply_c_ext, int32_t, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_BLN] = { eft_LNG, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_INT] = { @@ -1749,19 +1762,29 @@ static void func_map_init_elemwise_2arg_3type(func_map_t& fmap) fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_LNG] = { eft_LNG, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_FLT] = { - eft_DBL, (void*)dpnp_multiply_c_ext}; + eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_DBL] = { eft_DBL, (void*)dpnp_multiply_c_ext}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_C64] = { + eft_C64, (void*)dpnp_multiply_c_ext, int64_t, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_LNG][eft_C128] = { + eft_C128, (void*)dpnp_multiply_c_ext, int64_t, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_BLN] = { eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_INT] = { - eft_DBL, (void*)dpnp_multiply_c_ext}; + eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_LNG] = { - eft_DBL, (void*)dpnp_multiply_c_ext}; + eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_FLT] = { eft_FLT, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_DBL] = { eft_DBL, (void*)dpnp_multiply_c_ext}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_C64] = { + eft_C64, (void*)dpnp_multiply_c_ext, float, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_FLT][eft_C128] = { + eft_C128, (void*)dpnp_multiply_c_ext, float, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_DBL][eft_BLN] = { eft_DBL, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_DBL][eft_INT] = { @@ -1772,6 +1795,10 @@ static void func_map_init_elemwise_2arg_3type(func_map_t& fmap) eft_DBL, (void*)dpnp_multiply_c_ext}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_DBL][eft_DBL] = { eft_DBL, (void*)dpnp_multiply_c_ext}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_DBL][eft_C64] = { + eft_C64, (void*)dpnp_multiply_c_ext, double, std::complex>}; + fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_DBL][eft_C128] = { + eft_C128, (void*)dpnp_multiply_c_ext, double, std::complex>}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_C64][eft_BLN] = { eft_C64, (void*)dpnp_multiply_c_ext, std::complex, bool>}; @@ -1782,7 +1809,7 @@ static void func_map_init_elemwise_2arg_3type(func_map_t& fmap) fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_C64][eft_FLT] = { eft_C64, (void*)dpnp_multiply_c_ext, std::complex, float>}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_C64][eft_DBL] = { - eft_C128, (void*)dpnp_multiply_c_ext, std::complex, double>}; + eft_C64, (void*)dpnp_multiply_c_ext, std::complex, double>}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_C64][eft_C64] = { eft_C64, (void*)dpnp_multiply_c_ext, std::complex, std::complex>}; fmap[DPNPFuncName::DPNP_FN_MULTIPLY_EXT][eft_C64][eft_C128] = { diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index e3de357f7a40..2e842065492d 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -437,6 +437,7 @@ def asnumpy(self): Returns ------- + numpy.ndarray An instance of :class:`numpy.ndarray` populated with the array content. """ diff --git a/dpnp/dpnp_iface.py b/dpnp/dpnp_iface.py index b8a65797234d..4e791ad0eaf9 100644 --- a/dpnp/dpnp_iface.py +++ b/dpnp/dpnp_iface.py @@ -68,6 +68,10 @@ "get_normalized_queue_device" ] +from dpnp import ( + isscalar +) + from dpnp.dpnp_iface_arraycreation import * from dpnp.dpnp_iface_bitwise import * from dpnp.dpnp_iface_counting import * @@ -187,7 +191,10 @@ def convert_single_elem_array_to_scalar(obj, keepdims=False): return obj -def get_dpnp_descriptor(ext_obj, copy_when_strides=True, copy_when_nondefault_queue=True): +def get_dpnp_descriptor(ext_obj, + copy_when_strides=True, + copy_when_nondefault_queue=True, + alloc_queue=None): """ Return True: never @@ -206,6 +213,11 @@ def get_dpnp_descriptor(ext_obj, copy_when_strides=True, copy_when_nondefault_qu if use_origin_backend(): return False + # If input object is a scalar, it means it was allocated on host memory. + # We need to copy it to device memory according to compute follows data paradigm. + if isscalar(ext_obj): + ext_obj = array(ext_obj, sycl_queue=alloc_queue) + # while dpnp functions have no implementation with strides support # we need to create a non-strided copy # if function get implementation for strides case @@ -226,13 +238,12 @@ def get_dpnp_descriptor(ext_obj, copy_when_strides=True, copy_when_nondefault_qu # we need to create a copy on device associated with DPNP_QUEUE # if function get implementation for different queue # then this behavior can be disabled with setting "copy_when_nondefault_queue" - arr_obj = unwrap_array(ext_obj) - queue = getattr(arr_obj, "sycl_queue", None) + queue = getattr(ext_obj, "sycl_queue", None) if queue is not None and copy_when_nondefault_queue: default_queue = dpctl.SyclQueue() queue_is_default = dpctl.utils.get_execution_queue([queue, default_queue]) is not None if not queue_is_default: - ext_obj = array(arr_obj, sycl_queue=default_queue) + ext_obj = array(ext_obj, sycl_queue=default_queue) dpnp_desc = dpnp_descriptor(ext_obj) if dpnp_desc.is_valid: diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 45938f0d52ad..22f34f514ee0 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.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 @@ -131,12 +131,13 @@ def atleast_2d(*arys): all_is_array = True arys_desc = [] for ary in arys: - ary_desc = dpnp.get_dpnp_descriptor(ary, copy_when_nondefault_queue=False) - if ary_desc: - arys_desc.append(ary_desc) - else: - all_is_array = False - break + if not dpnp.isscalar(ary): + ary_desc = dpnp.get_dpnp_descriptor(ary, copy_when_nondefault_queue=False) + if ary_desc: + arys_desc.append(ary_desc) + continue + all_is_array = False + break if not use_origin_backend(arys[0]) and all_is_array: result = [] @@ -166,12 +167,13 @@ def atleast_3d(*arys): all_is_array = True arys_desc = [] for ary in arys: - ary_desc = dpnp.get_dpnp_descriptor(ary, copy_when_nondefault_queue=False) - if ary_desc: - arys_desc.append(ary_desc) - else: - all_is_array = False - break + if not dpnp.isscalar(ary): + ary_desc = dpnp.get_dpnp_descriptor(ary, copy_when_nondefault_queue=False) + if ary_desc: + arys_desc.append(ary_desc) + continue + all_is_array = False + break if not use_origin_backend(arys[0]) and all_is_array: result = [] diff --git a/dpnp/dpnp_iface_mathematical.py b/dpnp/dpnp_iface_mathematical.py index d4515b43cd3a..26b81a67dd95 100644 --- a/dpnp/dpnp_iface_mathematical.py +++ b/dpnp/dpnp_iface_mathematical.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 @@ -850,9 +850,9 @@ def fmod(x1, x2, dtype=None, out=None, where=True, **kwargs): pass elif x1_is_scalar and x2_is_scalar: pass - elif x1_desc and x1.ndim == 0: + elif x1_desc and x1_desc.ndim == 0: pass - elif x2_desc and x2.ndim == 0: + elif x2_desc and x2_desc.ndim == 0: pass elif dtype is not None: pass @@ -1075,51 +1075,62 @@ def modf(x1, **kwargs): return call_origin(numpy.modf, x1, **kwargs) -def multiply(x1, x2, dtype=None, out=None, where=True, **kwargs): +def multiply(x1, + x2, + /, + out=None, + *, + where=True, + dtype=None, + subok=True, + **kwargs): """ Multiply arguments element-wise. For full documentation refer to :obj:`numpy.multiply`. + Returns + ------- + y : {dpnp.ndarray, scalar} + The product of `x1` and `x2`, element-wise. + The result is a scalar if both x1 and x2 are scalars. + Limitations ----------- - Parameters ``x1`` and ``x2`` are supported as either :obj:`dpnp.ndarray` or scalar. - Parameters ``dtype``, ``out`` and ``where`` are supported with their default values. + Parameters `x1` and `x2` are supported as either :class:`dpnp.ndarray` or scalar. + Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. Keyword arguments ``kwargs`` are currently unsupported. Otherwise the functions will be executed sequentially on CPU. Input array data types are limited by supported DPNP :ref:`Data types`. Examples -------- - >>> import dpnp as np - >>> a = np.array([1, 2, 3, 4, 5]) - >>> result = np.multiply(a, a) - >>> [x for x in result] + >>> import dpnp as dp + >>> a = dp.array([1, 2, 3, 4, 5]) + >>> result = dp.multiply(a, a) + >>> print(result) [1, 4, 9, 16, 25] """ - x1_is_scalar = dpnp.isscalar(x1) - x2_is_scalar = dpnp.isscalar(x2) - x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_strides=False, copy_when_nondefault_queue=False) - x2_desc = dpnp.get_dpnp_descriptor(x2, copy_when_strides=False, copy_when_nondefault_queue=False) - - if x1_desc and x2_desc and not kwargs: - if not x2_desc and not x2_is_scalar: - pass - elif x1_is_scalar and x2_is_scalar: - pass - elif x1_desc and x1_desc.ndim == 0: - pass - elif x2_desc and x2_desc.ndim == 0: - pass - elif dtype is not None: - pass - elif out is not None: - pass - elif not where: - pass - else: + if out is not None: + pass + elif where is not True: + pass + elif dtype is not None: + pass + elif subok is not True: + pass + elif dpnp.isscalar(x1) and dpnp.isscalar(x2): + # keep the result in host memory, if both inputs are scalars + return x1 * x2 + else: + # get a common queue to copy data from the host into a device if any input is scalar + queue = get_common_allocation_queue([x1, x2]) if dpnp.isscalar(x1) or dpnp.isscalar(x2) else None + + x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_strides=False, copy_when_nondefault_queue=False, alloc_queue=queue) + x2_desc = dpnp.get_dpnp_descriptor(x2, copy_when_strides=False, copy_when_nondefault_queue=False, alloc_queue=queue) + if x1_desc and x2_desc: return dpnp_multiply(x1_desc, x2_desc, dtype=dtype, out=out, where=where).get_pyobj() return call_origin(numpy.multiply, x1, x2, dtype=dtype, out=out, where=where, **kwargs) diff --git a/dpnp/dpnp_utils/dpnp_algo_utils.pyx b/dpnp/dpnp_utils/dpnp_algo_utils.pyx index 8f95ee6b3b2b..c09bef8ec485 100644 --- a/dpnp/dpnp_utils/dpnp_algo_utils.pyx +++ b/dpnp/dpnp_utils/dpnp_algo_utils.pyx @@ -31,12 +31,22 @@ This module contains differnt helpers and utilities """ -import dpctl import numpy + +import dpctl +import dpctl.tensor as dpt + import dpnp.config as config import dpnp.dpnp_container as dpnp_container import dpnp -from dpnp.dpnp_algo.dpnp_algo cimport dpnp_DPNPFuncType_to_dtype, dpnp_dtype_to_DPNPFuncType, get_dpnp_function_ptr + +from dpnp.dpnp_array import dpnp_array +from dpnp.dpnp_algo.dpnp_algo cimport ( + dpnp_DPNPFuncType_to_dtype, + dpnp_dtype_to_DPNPFuncType, + get_dpnp_function_ptr +) + from libcpp cimport bool as cpp_bool from libcpp.complex cimport complex as cpp_complex @@ -60,6 +70,7 @@ __all__ = [ "dpnp_descriptor", "get_axis_indeces", "get_axis_offsets", + "get_common_allocation_queue", "_get_linear_index", "map_dtype_to_device", "normalize_axis", @@ -200,13 +211,39 @@ def call_origin(function, *args, **kwargs): def unwrap_array(x1): - """Get array from input object.""" - if isinstance(x1, dpnp.dpnp_array.dpnp_array): + """ + Get array from input object. + """ + if isinstance(x1, dpnp_array): return x1.get_array() return x1 +def get_common_allocation_queue(objects): + """ + Given a list of objects returns the queue which can be used for a memory allocation + to follow compute follows data paradigm, or returns `None` if the default queue can be used. + An exception will be raised, if the paradigm is broked for the given list of objects. + """ + if not isinstance(objects, (list, tuple)): + raise TypeError("Expected a list or a tuple, got {}".format(type(objects))) + + if len(objects) == 0: + return None + + queues_in_use = [obj.sycl_queue for obj in objects if hasattr(obj, "sycl_queue")] + if len(queues_in_use) == 0: + return None + elif len(queues_in_use) == 1: + return queues_in_use[0] + + common_queue = dpt.get_execution_queue(queues_in_use) + if common_queue is None: + raise ValueError("Input arrays must be allocated on the same SYCL queue") + return common_queue + + def map_dtype_to_device(dtype, device): """ Map an input ``dtype`` with type ``device`` may use @@ -675,6 +712,12 @@ cdef class dpnp_descriptor: return dpnp.dtype(type_str) return None + @property + def offset(self): + if self.is_valid: + return self.descriptor.get('offset', 0) + return 0 + @property def is_scalar(self): return self.dpnp_descriptor_is_scalar @@ -716,7 +759,7 @@ cdef class dpnp_descriptor: def get_array(self): if isinstance(self.origin_pyobj, dpctl.tensor.usm_ndarray): return self.origin_pyobj - if isinstance(self.origin_pyobj, dpnp.dpnp_array.dpnp_array): + if isinstance(self.origin_pyobj, dpnp_array): return self.origin_pyobj.get_array() raise TypeError( @@ -724,7 +767,17 @@ cdef class dpnp_descriptor: "".format(type(self.origin_pyobj))) cdef void * get_data(self): + cdef Py_ssize_t item_size = 0 + cdef Py_ssize_t elem_offset = 0 + cdef char *data_ptr = NULL cdef size_t val = self.data + + if self.offset > 0: + item_size = self.origin_pyobj.itemsize + elem_offset = self.offset + data_ptr = (val) + item_size * elem_offset + return < void * > data_ptr + return < void * > val def __bool__(self): diff --git a/dpnp/random/dpnp_random_state.py b/dpnp/random/dpnp_random_state.py index 6292bc77aedf..1d4648c31c47 100644 --- a/dpnp/random/dpnp_random_state.py +++ b/dpnp/random/dpnp_random_state.py @@ -60,19 +60,19 @@ class RandomState: Parameters ---------- + seed : {None, int, array_like}, optional + A random seed to initialize the pseudo-random number generator. + The `seed` can be ``None`` (the default), an integer scalar, or + an array_like of maximumum three integer scalars. device : {None, string, SyclDevice, SyclQueue}, optional An array API concept of device where the output array is created. - `device` can be ``None`` (the default), a oneAPI filter selector string, + The `device` can be ``None`` (the default), an OneAPI filter selector string, an instance of :class:`dpctl.SyclDevice` corresponding to a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`, or a `Device` object returned by :obj:`dpnp.dpnp_array.dpnp_array.device` property. sycl_queue : {None, SyclQueue}, optional - The SYCL queue to use for output array allocation and copying. + A SYCL queue to use for output array allocation and copying. - Limitations - ----------- - Parameter `seed` is supported as either a integer scalar or array_like - of maximumum three integer scalars. """ def __init__(self, seed=None, device=None, sycl_queue=None): @@ -197,7 +197,7 @@ def normal(self, loc=0.0, scale=1.0, size=None, dtype=None, usm_type="device"): Limitations ----------- - Parameters `loc` and `scale` are supported as scalar. Otherwise, + Parameters `loc` and `scale` are supported as a scalar. Otherwise, :obj:`numpy.random.RandomState.normal(loc, scale, size)` samples are drawn. Parameter `dtype` is supported only as :obj:`dpnp.float32`, :obj:`dpnp.float64` or ``None``. @@ -314,7 +314,7 @@ def randint(self, low, high=None, size=None, dtype=int, usm_type="device"): Parameters `low` and `high` are supported only as a scalar. Parameter `dtype` is supported only as :obj:`dpnp.int32` or ``int``, but ``int`` value is considered to be exactly equivalent to :obj:`dpnp.int32`. - Otherwise, :obj:`numpy.random.randint(low, high, size, dtype)` samples are drawn. + Otherwise, :obj:`numpy.random.RandomState.randint(low, high, size, dtype)` samples are drawn. Examples -------- @@ -518,8 +518,8 @@ def uniform(self, low=0.0, high=1.0, size=None, dtype=None, usm_type="device"): Limitations ----------- - Parameters `low` and `high` are supported as scalar. Otherwise, - :obj:`numpy.random.uniform(low, high, size)` samples are drawn. + Parameters `low` and `high` are supported as a scalar. Otherwise, + :obj:`numpy.random.RandomState.uniform(low, high, size)` samples are drawn. Parameter `dtype` is supported only as :obj:`dpnp.int32`, :obj:`dpnp.float32`, :obj:`dpnp.float64` or ``None``. Examples diff --git a/tests/skipped_tests.tbl b/tests/skipped_tests.tbl index 17c9688cb446..2f7077738c37 100644 --- a/tests/skipped_tests.tbl +++ b/tests/skipped_tests.tbl @@ -198,8 +198,6 @@ tests/test_linalg.py::test_svd[(3,4)-float64] tests/test_linalg.py::test_svd[(5,3)-float64] tests/test_linalg.py::test_svd[(16,16)-float64] -tests/test_mathematical.py::TestGradient::test_gradient_y1_dx[3.5-array1] - tests/test_random.py::TestPermutationsTestShuffle::test_shuffle1[lambda x: dpnp.asarray([[i, i] for i in x])] tests/test_random.py::TestPermutationsTestShuffle::test_shuffle1[lambda x: (dpnp.asarray([(i, i) for i in x], [("a", int), ("b", int)]).view(dpnp.recarray))] tests/test_random.py::TestPermutationsTestShuffle::test_shuffle1[lambda x: dpnp.asarray([(i, i) for i in x], [("a", object), ("b", dpnp.int32)])]] @@ -800,7 +798,6 @@ tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNu tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_11_{name='mod', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_1_{name='angle', nargs=1}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_2_{name='add', nargs=2}::test_raises_with_numpy_input -tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_3_{name='multiply', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_4_{name='divide', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_5_{name='power', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_6_{name='subtract', nargs=2}::test_raises_with_numpy_input diff --git a/tests/skipped_tests_gpu.tbl b/tests/skipped_tests_gpu.tbl index e182e37b5a3d..19441fa1e6d8 100644 --- a/tests/skipped_tests_gpu.tbl +++ b/tests/skipped_tests_gpu.tbl @@ -23,27 +23,6 @@ tests/test_sycl_queue.py::test_1in_1out[opencl:gpu:0-ediff1d-data7] tests/test_sycl_queue.py::test_1in_1out[opencl:gpu:0-fabs-data8] tests/test_sycl_queue.py::test_1in_1out[opencl:gpu:0-floor-data9] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-add-data10-data20] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-copysign-data11-data21] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-cross-data12-data22] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-divide-data13-data23] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-floor_divide-data14-data24] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-fmod-data15-data25] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-maximum-data16-data26] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-minimum-data17-data27] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-multiply-data18-data28] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-power-data19-data29] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-remainder-data110-data210] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-subtract-data111-data211] -tests/test_sycl_queue.py::test_2in_1out[opencl:gpu:0-matmul-data112-data212] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-add-data10-data20] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-divide-data11-data21] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-floor_divide-data12-data22] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-fmod-data13-data23] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-multiply-data14-data24] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-remainder-data15-data25] -tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-subtract-data16-data26] - tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-abs-data0] tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-ceil-data1] tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-conjugate-data2] @@ -65,46 +44,19 @@ tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-sign-data17] tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-sum-data18] tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-trapz-data19] tests/test_sycl_queue.py::test_1in_1out[level_zero:gpu:0-trunc-data20] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-add-data10-data20] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-copysign-data11-data21] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-cross-data12-data22] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-divide-data13-data23] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-floor_divide-data14-data24] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-fmod-data15-data25] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-maximum-data16-data26] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-minimum-data17-data27] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-multiply-data18-data28] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-power-data19-data29] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-remainder-data110-data210] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-subtract-data111-data211] -tests/test_sycl_queue.py::test_2in_1out[level_zero:gpu:0-matmul-data112-data212] -tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-add-data10-data20] -tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-divide-data11-data21] + tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-floor_divide-data12-data22] -tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-fmod-data13-data23] -tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-multiply-data14-data24] tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-remainder-data15-data25] -tests/test_sycl_queue.py::test_broadcasting[level_zero:gpu:0-subtract-data16-data26] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-add-data10-data20] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-copysign-data11-data21] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-divide-data12-data22] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-floor_divide-data13-data23] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-fmod-data14-data24] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-maximum-data15-data25] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-minimum-data16-data26] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-multiply-data17-data27] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-power-data18-data28] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-remainder-data19-data29] -tests/test_sycl_queue.py::test_out[level_zero:gpu:0-subtract-data110-data210] -tests/test_sycl_queue.py::test_modf[level_zero:gpu:0] - -tests/test_sycl_queue.py::test_1in_1out[opencl:gpu:0-trapz-data19] -tests/test_sycl_queue.py::test_1in_1out[opencl:cpu:0-trapz-data19] tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-floor_divide-data12-data22] tests/test_sycl_queue.py::test_broadcasting[opencl:gpu:0-remainder-data15-data25] tests/test_sycl_queue.py::test_broadcasting[opencl:cpu:0-floor_divide-data12-data22] tests/test_sycl_queue.py::test_broadcasting[opencl:cpu:0-remainder-data15-data25] +tests/test_sycl_queue.py::test_modf[level_zero:gpu:0] + +tests/test_sycl_queue.py::test_1in_1out[opencl:gpu:0-trapz-data19] +tests/test_sycl_queue.py::test_1in_1out[opencl:cpu:0-trapz-data19] + tests/test_indexing.py::test_nonzero[[[1, 0], [1, 0]]] tests/test_indexing.py::test_nonzero[[[1, 2], [3, 4]]] tests/test_indexing.py::test_nonzero[[[0, 1, 2], [3, 0, 5], [6, 7, 0]]] @@ -211,12 +163,6 @@ tests/test_random.py::TestPermutationsTestShuffle::test_shuffle1[lambda x: dpnp. tests/test_arraymanipulation.py::TestConcatenate::test_concatenate tests/test_histograms.py::TestHistogram::test_density -tests/test_mathematical.py::TestGradient::test_gradient_y1[array0] -tests/test_mathematical.py::TestGradient::test_gradient_y1[array1] -tests/test_mathematical.py::TestGradient::test_gradient_y1[array2] -tests/test_mathematical.py::TestGradient::test_gradient_y1_dx[2-array0] -tests/test_mathematical.py::TestGradient::test_gradient_y1_dx[2-array1] -tests/test_mathematical.py::TestGradient::test_gradient_y1_dx[2-array2] tests/test_random.py::TestPermutationsTestShuffle::test_shuffle1[lambda x: dpnp.astype(dpnp.asarray(x), dpnp.int8)] tests/test_random.py::TestPermutationsTestShuffle::test_shuffle1[lambda x: dpnp.astype(dpnp.asarray(x), object)] @@ -1072,7 +1018,6 @@ tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNu tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_11_{name='mod', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_1_{name='angle', nargs=1}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_2_{name='add', nargs=2}::test_raises_with_numpy_input -tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_3_{name='multiply', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_4_{name='divide', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_5_{name='power', nargs=2}::test_raises_with_numpy_input tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_6_{name='subtract', nargs=2}::test_raises_with_numpy_input diff --git a/tests/test_mathematical.py b/tests/test_mathematical.py index 63d63f131994..21071bec41e9 100644 --- a/tests/test_mathematical.py +++ b/tests/test_mathematical.py @@ -56,7 +56,6 @@ def test_diff(array): numpy.testing.assert_allclose(expected, result) -@pytest.mark.usefixtures("allow_fall_back_on_numpy") @pytest.mark.parametrize("dtype1", [numpy.bool_, numpy.float64, numpy.float32, numpy.int64, numpy.int32, numpy.complex64, numpy.complex128], ids=['numpy.bool_', 'numpy.float64', 'numpy.float32', 'numpy.int64', 'numpy.int32', 'numpy.complex64', 'numpy.complex128']) @@ -73,7 +72,7 @@ def test_multiply_dtype(dtype1, dtype2, data): np_b = numpy.array(data, dtype=dtype2) dpnp_b = dpnp.array(data, dtype=dtype2) - result = numpy.multiply(dpnp_a, dpnp_b) + result = dpnp.multiply(dpnp_a, dpnp_b) expected = numpy.multiply(np_a, np_b) numpy.testing.assert_array_equal(result, expected) @@ -137,7 +136,6 @@ def test_maximum(self, dtype, lhs, rhs): def test_minimum(self, dtype, lhs, rhs): self._test_mathematical('minimum', dtype, lhs, rhs) - @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_multiply(self, dtype, lhs, rhs): self._test_mathematical('multiply', dtype, lhs, rhs) @@ -154,7 +152,6 @@ def test_subtract(self, dtype, lhs, rhs): self._test_mathematical('subtract', dtype, lhs, rhs) -@pytest.mark.usefixtures("allow_fall_back_on_numpy") @pytest.mark.parametrize("val_type", [bool, int, float], ids=['bool', 'int', 'float']) @@ -180,16 +177,15 @@ def test_multiply_scalar(array, val, data_type, val_type): dpnp_a = dpnp.array(array, dtype=data_type) val_ = val_type(val) - result = dpnp.multiply(np_a, val_) - expected = numpy.multiply(dpnp_a, val_) + result = dpnp.multiply(dpnp_a, val_) + expected = numpy.multiply(np_a, val_) numpy.testing.assert_array_equal(result, expected) - result = dpnp.multiply(val_, np_a) - expected = numpy.multiply(val_, dpnp_a) + result = dpnp.multiply(val_, dpnp_a) + expected = numpy.multiply(val_, np_a) numpy.testing.assert_array_equal(result, expected) -@pytest.mark.usefixtures("allow_fall_back_on_numpy") @pytest.mark.parametrize("shape", [(), (3, 2)], ids=['()', '(3, 2)']) diff --git a/tests/third_party/cupy/math_tests/test_arithmetic.py b/tests/third_party/cupy/math_tests/test_arithmetic.py index 9f5e8994b70f..28771b4979b5 100644 --- a/tests/third_party/cupy/math_tests/test_arithmetic.py +++ b/tests/third_party/cupy/math_tests/test_arithmetic.py @@ -144,6 +144,33 @@ def check_binary(self, xp): if dtype1 in (numpy.float16, numpy.float32): y = y.astype(numpy.complex64) + # NumPy returns an output array of another type than DPNP when input ones have diffrent types. + if self.name == 'multiply' and xp is cupy: + if xp.isscalar(arg1) and xp.isscalar(arg2): + # If both are scalars, the result will be a scalar, so needs to convert into numpy-scalar. + y = numpy.asarray(y) + elif dtype1 != dtype2: + is_array_arg1 = not xp.isscalar(arg1) + is_array_arg2 = not xp.isscalar(arg2) + + is_int_float = lambda _x, _y: numpy.issubdtype(_x, numpy.integer) and numpy.issubdtype(_y, numpy.floating) + is_same_type = lambda _x, _y, _type: numpy.issubdtype(_x, _type) and numpy.issubdtype(_y, _type) + + if is_array_arg1 and is_array_arg2: + # If both inputs are arrays where one is of floating type and another - integer, + # NumPy will return an output array of always "float64" type, + # while DPNP will return the array of a wider type from the input arrays. + if is_int_float(dtype1, dtype2) or is_int_float(dtype2, dtype1): + y = y.astype(numpy.float64) + elif is_same_type(dtype1, dtype2, numpy.floating) or is_same_type(dtype1, dtype2, numpy.integer): + # If one input is an array and another - scalar, + # NumPy will return an output array of the same type as the inpupt array has, + # while DPNP will return the array of a wider type from the inputs (considering both array and scalar). + if is_array_arg1 and not is_array_arg2: + y = y.astype(dtype1) + elif is_array_arg2 and not is_array_arg1: + y = y.astype(dtype2) + # NumPy returns different values (nan/inf) on division by zero # depending on the architecture. # As it is not possible for CuPy to replicate this behavior, we ignore