From 4177d2186617fdf628c897ea4e521edb38b996dc Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 7 Aug 2023 12:09:43 +0200 Subject: [PATCH 1/2] Leveraged dpctl.tensor.stack() implementation --- .github/workflows/conda-package.yml | 2 + dpnp/dpnp_iface_manipulation.py | 71 +++++- tests/conftest.py | 8 + tests/test_arraymanipulation.py | 227 ++++++++++++++++-- .../cupy/manipulation_tests/test_join.py | 79 +++--- 5 files changed, 318 insertions(+), 69 deletions(-) diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 096f7a10bbf..9ad801cf5fd 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -12,6 +12,7 @@ env: CHANNELS: '-c dppy/label/dev -c intel -c conda-forge --override-channels' TEST_SCOPE: >- test_arraycreation.py + test_arraymanipulation.py test_dot.py test_dparray.py test_fft.py @@ -23,6 +24,7 @@ env: test_umath.py test_usm_type.py third_party/cupy/linalg_tests/test_product.py + third_party/cupy/manipulation_tests/test_join.py third_party/cupy/math_tests/test_explog.py third_party/cupy/math_tests/test_misc.py third_party/cupy/math_tests/test_trigonometric.py diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index fca218be02f..5f5dcb3617d 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -237,7 +237,7 @@ def broadcast_to(x, /, shape, subok=False): return call_origin(numpy.broadcast_to, x, shape=shape, subok=subok) -def concatenate(arrays, *, axis=0, out=None, dtype=None, **kwargs): +def concatenate(arrays, /, *, axis=0, out=None, dtype=None, **kwargs): """ Join a sequence of arrays along an existing axis. @@ -253,8 +253,7 @@ def concatenate(arrays, *, axis=0, out=None, dtype=None, **kwargs): Each array in `arrays` is supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. Otherwise ``TypeError`` exeption will be raised. - Parameter `out` is supported with default value. - Parameter `dtype` is supported with default value. + Parameters `out` and `dtype are supported with default value. Keyword argument ``kwargs`` is currently unsupported. Otherwise the function will be executed sequentially on CPU. @@ -834,15 +833,77 @@ def squeeze(x, /, axis=None): return call_origin(numpy.squeeze, x, axis) -def stack(arrays, axis=0, out=None): +def stack(arrays, /, *, axis=0, out=None, dtype=None, **kwargs): """ Join a sequence of arrays along a new axis. For full documentation refer to :obj:`numpy.stack`. + Returns + ------- + out : dpnp.ndarray + The stacked array which has one more dimension than the input arrays. + + Limitations + ----------- + Each array in `arrays` is supported as either :class:`dpnp.ndarray` + or :class:`dpctl.tensor.usm_ndarray`. Otherwise ``TypeError`` exeption + will be raised. + Parameters `out` and `dtype are supported with default value. + Keyword argument ``kwargs`` is currently unsupported. + Otherwise the function will be executed sequentially on CPU. + + See Also + -------- + :obj:`dpnp.concatenate` : Join a sequence of arrays along an existing axis. + :obj:`dpnp.block` : Assemble an nd-array from nested lists of blocks. + :obj:`dpnp.split` : Split array into a list of multiple sub-arrays of equal size. + + Examples + -------- + >>> import dpnp as np + >>> arrays = [np.random.randn(3, 4) for _ in range(10)] + >>> np.stack(arrays, axis=0).shape + (10, 3, 4) + + >>> np.stack(arrays, axis=1).shape + (3, 10, 4) + + >>> np.stack(arrays, axis=2).shape + (3, 4, 10) + + >>> a = np.array([1, 2, 3]) + >>> b = np.array([4, 5, 6]) + >>> np.stack((a, b)) + array([[1, 2, 3], + [4, 5, 6]]) + + >>> np.stack((a, b), axis=-1) + array([[1, 4], + [2, 5], + [3, 6]]) + """ - return call_origin(numpy.stack, arrays, axis, out) + if kwargs: + pass + elif out is not None: + pass + elif dtype is not None: + pass + else: + usm_arrays = [dpnp.get_usm_ndarray(x) for x in arrays] + usm_res = dpt.stack(usm_arrays, axis=axis) + return dpnp_array._create_from_usm_ndarray(usm_res) + + return call_origin( + numpy.stack, + arrays, + axis=axis, + out=out, + dtype=dtype, + **kwargs, + ) def swapaxes(x1, axis1, axis2): diff --git a/tests/conftest.py b/tests/conftest.py index 49b6692a132..ee37c6a68aa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -83,6 +83,14 @@ def allow_fall_back_on_numpy(monkeypatch): ) +@pytest.fixture +def suppress_complex_warning(): + sup = numpy.testing.suppress_warnings("always") + sup.filter(numpy.ComplexWarning) + with sup: + yield + + @pytest.fixture def suppress_divide_numpy_warnings(): # divide: treatment for division by zero (infinite result obtained from finite numbers) diff --git a/tests/test_arraymanipulation.py b/tests/test_arraymanipulation.py index 68e8f4af47a..94f54accbc7 100644 --- a/tests/test_arraymanipulation.py +++ b/tests/test_arraymanipulation.py @@ -1,7 +1,6 @@ import numpy import pytest from numpy.testing import ( - assert_, assert_allclose, assert_array_equal, assert_equal, @@ -11,7 +10,7 @@ import dpnp -from .helper import get_all_dtypes +from .helper import get_all_dtypes, get_float_complex_dtypes @pytest.mark.usefixtures("allow_fall_back_on_numpy") @@ -145,9 +144,12 @@ def test_axis_exceptions(self, ndim): assert_equal(dp_res.asnumpy(), np_res) for axis in [ndim, -(ndim + 1)]: - with pytest.raises(numpy.AxisError): - dpnp.concatenate((dp_a, dp_a), axis=axis) - numpy.concatenate((np_a, np_a), axis=axis) + assert_raises( + numpy.AxisError, dpnp.concatenate, (dp_a, dp_a), axis=axis + ) + assert_raises( + numpy.AxisError, numpy.concatenate, (np_a, np_a), axis=axis + ) def test_scalar_exceptions(self): assert_raises(TypeError, dpnp.concatenate, (0,)) @@ -177,9 +179,12 @@ def test_shapes_match_exception(self): assert_equal(dp_res.asnumpy(), np_res) for i in range(1, 3): - with pytest.raises(ValueError): - numpy.concatenate((np_a, np_b), axis=axis[i]) - dpnp.concatenate((dp_a, dp_b), axis=axis[i]) + assert_raises( + ValueError, numpy.concatenate, (np_a, np_b), axis=axis[i] + ) + assert_raises( + ValueError, dpnp.concatenate, (dp_a, dp_b), axis=axis[i] + ) np_a = numpy.moveaxis(np_a, -1, 0) dp_a = dpnp.moveaxis(dp_a, -1, 0) @@ -189,8 +194,7 @@ def test_shapes_match_exception(self): axis.append(axis.pop(0)) def test_no_array_exception(self): - with pytest.raises(ValueError): - numpy.concatenate(()) + with pytest.raises(TypeError): dpnp.concatenate(()) @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @@ -272,9 +276,12 @@ def test_concatenate_2d(self, dtype): assert_array_equal(dp_res.asnumpy(), np_res) # Arrays much match shape - with pytest.raises(ValueError): - numpy.concatenate((np_a23.T, np_a13.T), axis=0) - dpnp.concatenate((dp_a23.T, dp_a13.T), axis=0) + assert_raises( + ValueError, numpy.concatenate, (np_a23.T, np_a13.T), axis=0 + ) + assert_raises( + ValueError, dpnp.concatenate, (dp_a23.T, dp_a13.T), axis=0 + ) @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_none=True) @@ -299,7 +306,7 @@ def test_concatenate_3d(self, dtype): dp_res = dpnp.concatenate((dp_a0.T, dp_a1.T, dp_a2.T), axis=0) assert_array_equal(dp_res.asnumpy(), np_res) - @pytest.mark.skip("out keyword is currently unsupported") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_none=True) ) @@ -363,6 +370,198 @@ def test_generator(self): dpnp.hstack(map(lambda x: x, numpy.ones((3, 2)))) +class TestStack: + def test_non_iterable_input(self): + with pytest.raises(TypeError): + dpnp.stack(1) + + @pytest.mark.parametrize( + "input", [(1, 2, 3), [dpnp.int32(1), dpnp.int32(2), dpnp.int32(3)]] + ) + def test_scalar_input(self, input): + with pytest.raises(TypeError): + dpnp.stack(input) + + @pytest.mark.parametrize("dtype", get_all_dtypes()) + def test_0d_array_input(self, dtype): + np_arrays = [] + dp_arrays = [] + + for x in (1, 2, 3): + np_arrays.append(numpy.array(x, dtype=dtype)) + dp_arrays.append(dpnp.array(x, dtype=dtype)) + + np_res = numpy.stack(np_arrays) + dp_res = dpnp.stack(dp_arrays) + assert_array_equal(dp_res.asnumpy(), np_res) + + @pytest.mark.parametrize("dtype", get_all_dtypes()) + def test_1d_array_input(self, dtype): + np_a = numpy.array([1, 2, 3], dtype=dtype) + np_b = numpy.array([4, 5, 6], dtype=dtype) + dp_a = dpnp.array(np_a, dtype=dtype) + dp_b = dpnp.array(np_b, dtype=dtype) + + np_res = numpy.stack((np_a, np_b)) + dp_res = dpnp.stack((dp_a, dp_b)) + assert_array_equal(dp_res.asnumpy(), np_res) + + np_res = numpy.stack((np_a, np_b), axis=1) + dp_res = dpnp.stack((dp_a, dp_b), axis=1) + assert_array_equal(dp_res.asnumpy(), np_res) + + np_res = numpy.stack(list([np_a, np_b])) + dp_res = dpnp.stack(list([dp_a, dp_b])) + assert_array_equal(dp_res.asnumpy(), np_res) + + np_res = numpy.stack(numpy.array([np_a, np_b])) + dp_res = dpnp.stack(dpnp.array([dp_a, dp_b])) + assert_array_equal(dp_res.asnumpy(), np_res) + + @pytest.mark.parametrize("axis", [0, 1, -1, -2]) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_none=True) + ) + def test_1d_array_axis(self, axis, dtype): + arrays = [numpy.random.randn(3) for _ in range(10)] + np_arrays = numpy.array(arrays, dtype=dtype) + dp_arrays = dpnp.array(arrays, dtype=dtype) + + np_res = numpy.stack(np_arrays, axis=axis) + dp_res = dpnp.stack(dp_arrays, axis=axis) + assert_array_equal(dp_res.asnumpy(), np_res) + + @pytest.mark.parametrize("axis", [2, -3]) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_none=True) + ) + def test_1d_array_invalid_axis(self, axis, dtype): + arrays = [numpy.random.randn(3) for _ in range(10)] + np_arrays = numpy.array(arrays, dtype=dtype) + dp_arrays = dpnp.array(arrays, dtype=dtype) + + assert_raises(numpy.AxisError, numpy.stack, np_arrays, axis=axis) + assert_raises(numpy.AxisError, dpnp.stack, dp_arrays, axis=axis) + + @pytest.mark.parametrize("axis", [0, 1, 2, -1, -2, -3]) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_none=True) + ) + def test_2d_array_axis(self, axis, dtype): + arrays = [numpy.random.randn(3, 4) for _ in range(10)] + np_arrays = numpy.array(arrays, dtype=dtype) + dp_arrays = dpnp.array(arrays, dtype=dtype) + + np_res = numpy.stack(np_arrays, axis=axis) + dp_res = dpnp.stack(dp_arrays, axis=axis) + assert_array_equal(dp_res.asnumpy(), np_res) + + @pytest.mark.parametrize("dtype", get_all_dtypes()) + def test_empty_arrays_input(self, dtype): + arrays = [[], [], []] + np_arrays = numpy.array(arrays, dtype=dtype) + dp_arrays = dpnp.array(arrays, dtype=dtype) + + np_res = numpy.stack(np_arrays) + dp_res = dpnp.stack(dp_arrays) + assert_array_equal(dp_res.asnumpy(), np_res) + + np_res = numpy.stack(np_arrays, axis=1) + dp_res = dpnp.stack(dp_arrays, axis=1) + assert_array_equal(dp_res.asnumpy(), np_res) + + @pytest.mark.usefixtures("allow_fall_back_on_numpy") + @pytest.mark.parametrize("dtype", get_all_dtypes()) + def test_out(self, dtype): + np_a = numpy.array([1, 2, 3], dtype=dtype) + np_b = numpy.array([4, 5, 6], dtype=dtype) + dp_a = dpnp.array(np_a, dtype=dtype) + dp_b = dpnp.array(np_b, dtype=dtype) + + np_out = numpy.empty_like(np_a, shape=(2, 3)) + dp_out = dpnp.empty_like(dp_a, shape=(2, 3)) + + np_res = numpy.stack((np_a, np_b), out=np_out) + dp_res = dpnp.stack((dp_a, dp_b), out=dp_out) + + assert dp_out is dp_res + assert_array_equal(dp_out.asnumpy(), np_out) + assert_array_equal(dp_res.asnumpy(), np_res) + + def test_empty_list_input(self): + with pytest.raises(TypeError): + dpnp.stack([]) + + @pytest.mark.parametrize( + "sh1, sh2", + [ + pytest.param((), (3,), id="()-(3,)"), + pytest.param((3,), (), id="(3,)-()"), + pytest.param((3, 3), (3,), id="(3, 3)-(3,)"), + pytest.param((2,), (3,), id="(2,)-(3,)"), + ], + ) + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_none=True) + ) + def test_invalid_shapes_input(self, sh1, sh2, dtype): + np_a = numpy.ones(sh1, dtype=dtype) + np_b = numpy.ones(sh2, dtype=dtype) + dp_a = dpnp.array(np_a, dtype=dtype) + dp_b = dpnp.array(np_b, dtype=dtype) + + assert_raises(ValueError, numpy.stack, [np_a, np_b]) + assert_raises(ValueError, dpnp.stack, [dp_a, dp_b]) + assert_raises(ValueError, numpy.stack, [np_a, np_b], axis=1) + assert_raises(ValueError, dpnp.stack, [dp_a, dp_b], axis=1) + + def test_generator_input(self): + with pytest.raises(TypeError): + dpnp.stack((x for x in range(3))) + + @pytest.mark.usefixtures("allow_fall_back_on_numpy") + @pytest.mark.usefixtures("suppress_complex_warning") + @pytest.mark.parametrize("arr_dtype", get_all_dtypes()) + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) + def test_casting_dtype(self, arr_dtype, dtype): + np_a = numpy.array([1, 2, 3], dtype=arr_dtype) + np_b = numpy.array([2.5, 3.5, 4.5], dtype=arr_dtype) + dp_a = dpnp.array(np_a, dtype=arr_dtype) + dp_b = dpnp.array(np_b, dtype=arr_dtype) + + np_res = numpy.stack( + (np_a, np_b), axis=1, casting="unsafe", dtype=dtype + ) + dp_res = dpnp.stack((dp_a, dp_b), axis=1, casting="unsafe", dtype=dtype) + assert_array_equal(dp_res.asnumpy(), np_res) + + @pytest.mark.usefixtures("allow_fall_back_on_numpy") + @pytest.mark.parametrize("arr_dtype", get_float_complex_dtypes()) + @pytest.mark.parametrize("dtype", [dpnp.bool, dpnp.int32, dpnp.int64]) + def test_invalid_casting_dtype(self, arr_dtype, dtype): + np_a = numpy.array([1, 2, 3], dtype=arr_dtype) + np_b = numpy.array([2.5, 3.5, 4.5], dtype=arr_dtype) + dp_a = dpnp.array(np_a, dtype=arr_dtype) + dp_b = dpnp.array(np_b, dtype=arr_dtype) + + assert_raises( + TypeError, + numpy.stack, + (np_a, np_b), + axis=1, + casting="safe", + dtype=dtype, + ) + assert_raises( + TypeError, + dpnp.stack, + (dp_a, dp_b), + axis=1, + casting="safe", + dtype=dtype, + ) + + class TestVstack: def test_non_iterable(self): assert_raises(TypeError, dpnp.vstack, 1) diff --git a/tests/third_party/cupy/manipulation_tests/test_join.py b/tests/third_party/cupy/manipulation_tests/test_join.py index e302065ca99..054ada455ae 100644 --- a/tests/third_party/cupy/manipulation_tests/test_join.py +++ b/tests/third_party/cupy/manipulation_tests/test_join.py @@ -375,7 +375,6 @@ def test_vstack_casting(self, xp, dtype1, dtype2, casting): # may raise TypeError or ComplexWarning return xp.vstack((a, b), dtype=dtype2, casting=casting) - @pytest.mark.skip("dpnp.stack() is not implemented yet") @testing.numpy_cupy_array_equal() def test_stack(self, xp): a = testing.shaped_arange((2, 3), xp) @@ -383,61 +382,53 @@ def test_stack(self, xp): c = testing.shaped_arange((2, 3), xp) return xp.stack((a, b, c)) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_value(self): a = testing.shaped_arange((2, 3), cupy) b = testing.shaped_arange((2, 3), cupy) c = testing.shaped_arange((2, 3), cupy) s = cupy.stack((a, b, c)) assert s.shape == (3, 2, 3) - cupy.testing.assert_array_equal(s[0], a) - cupy.testing.assert_array_equal(s[1], b) - cupy.testing.assert_array_equal(s[2], c) + testing.assert_array_equal(s[0], a) + testing.assert_array_equal(s[1], b) + testing.assert_array_equal(s[2], c) - @pytest.mark.skip("dpnp.stack() is not implemented yet") @testing.numpy_cupy_array_equal() def test_stack_with_axis1(self, xp): a = testing.shaped_arange((2, 3), xp) return xp.stack((a, a), axis=1) - @pytest.mark.skip("dpnp.stack() is not implemented yet") @testing.numpy_cupy_array_equal() def test_stack_with_axis2(self, xp): a = testing.shaped_arange((2, 3), xp) return xp.stack((a, a), axis=2) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_with_axis_over(self): for xp in (numpy, cupy): a = testing.shaped_arange((2, 3), xp) with pytest.raises(ValueError): xp.stack((a, a), axis=3) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_with_axis_value(self): a = testing.shaped_arange((2, 3), cupy) s = cupy.stack((a, a), axis=1) assert s.shape == (2, 2, 3) - cupy.testing.assert_array_equal(s[:, 0, :], a) - cupy.testing.assert_array_equal(s[:, 1, :], a) + testing.assert_array_equal(s[:, 0, :], a) + testing.assert_array_equal(s[:, 1, :], a) - @pytest.mark.skip("dpnp.stack() is not implemented yet") @testing.numpy_cupy_array_equal() def test_stack_with_negative_axis(self, xp): a = testing.shaped_arange((2, 3), xp) return xp.stack((a, a), axis=-1) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_with_negative_axis_value(self): a = testing.shaped_arange((2, 3), cupy) s = cupy.stack((a, a), axis=-1) assert s.shape == (2, 3, 2) - cupy.testing.assert_array_equal(s[:, :, 0], a) - cupy.testing.assert_array_equal(s[:, :, 1], a) + testing.assert_array_equal(s[:, :, 0], a) + testing.assert_array_equal(s[:, :, 1], a) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_different_shape(self): for xp in (numpy, cupy): a = testing.shaped_arange((2, 3), xp) @@ -445,20 +436,18 @@ def test_stack_different_shape(self): with pytest.raises(ValueError): xp.stack([a, b]) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_out_of_bounds1(self): for xp in (numpy, cupy): a = testing.shaped_arange((2, 3), xp) with pytest.raises(ValueError): xp.stack([a, a], axis=3) - @pytest.mark.skip("dpnp.stack() is not implemented yet") def test_stack_out_of_bounds2(self): a = testing.shaped_arange((2, 3), cupy) with pytest.raises(numpy.AxisError): return cupy.stack([a, a], axis=3) - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.for_all_dtypes(name="dtype") @testing.numpy_cupy_array_equal() def test_stack_out(self, xp, dtype): @@ -469,47 +458,47 @@ def test_stack_out(self, xp, dtype): xp.stack((a, b, c), axis=1, out=out) return out - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.numpy_cupy_array_equal() def test_stack_out_same_kind(self, xp): - a = testing.shaped_arange((3, 4), xp, xp.float64) - b = testing.shaped_reverse_arange((3, 4), xp, xp.float64) - c = testing.shaped_arange((3, 4), xp, xp.float64) + a = testing.shaped_arange((3, 4), xp, xp.float32) + b = testing.shaped_reverse_arange((3, 4), xp, xp.float32) + c = testing.shaped_arange((3, 4), xp, xp.float32) out = xp.zeros((3, 3, 4), dtype=xp.float32) xp.stack((a, b, c), axis=1, out=out) return out - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_stack_out_invalid_shape(self): for xp in (numpy, cupy): - a = testing.shaped_arange((3, 4), xp, xp.float64) - b = testing.shaped_reverse_arange((3, 4), xp, xp.float64) - c = testing.shaped_arange((3, 4), xp, xp.float64) - out = xp.zeros((3, 3, 10), dtype=xp.float64) + a = testing.shaped_arange((3, 4), xp, xp.float32) + b = testing.shaped_reverse_arange((3, 4), xp, xp.float32) + c = testing.shaped_arange((3, 4), xp, xp.float32) + out = xp.zeros((3, 3, 10), dtype=xp.float32) with pytest.raises(ValueError): xp.stack((a, b, c), axis=1, out=out) - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_stack_out_invalid_shape_2(self): for xp in (numpy, cupy): - a = testing.shaped_arange((3, 4), xp, xp.float64) - b = testing.shaped_reverse_arange((3, 4), xp, xp.float64) - c = testing.shaped_arange((3, 4), xp, xp.float64) - out = xp.zeros((3, 3, 3, 10), dtype=xp.float64) + a = testing.shaped_arange((3, 4), xp, xp.float32) + b = testing.shaped_reverse_arange((3, 4), xp, xp.float32) + c = testing.shaped_arange((3, 4), xp, xp.float32) + out = xp.zeros((3, 3, 3, 10), dtype=xp.float32) with pytest.raises(ValueError): xp.stack((a, b, c), axis=1, out=out) - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") def test_stack_out_invalid_dtype(self): for xp in (numpy, cupy): - a = testing.shaped_arange((3, 4), xp, xp.float64) - b = testing.shaped_reverse_arange((3, 4), xp, xp.float64) - c = testing.shaped_arange((3, 4), xp, xp.float64) + a = testing.shaped_arange((3, 4), xp, xp.float32) + b = testing.shaped_reverse_arange((3, 4), xp, xp.float32) + c = testing.shaped_arange((3, 4), xp, xp.float32) out = xp.zeros((3, 3, 4), dtype=xp.int64) with pytest.raises(TypeError): xp.stack((a, b, c), axis=1, out=out) - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.with_requires("numpy>=1.24.0") @testing.for_all_dtypes_combination(names=["dtype1", "dtype2"]) @testing.numpy_cupy_array_equal(accept_error=TypeError) @@ -518,18 +507,9 @@ def test_stack_dtype(self, xp, dtype1, dtype2): b = testing.shaped_arange((3, 4), xp, dtype1) return xp.stack((a, b), dtype=dtype2) - @pytest.mark.skip("dpnp.stack() is not implemented yet") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") @testing.with_requires("numpy>=1.24.0") - @pytest.mark.parametrize( - "casting", - [ - "no", - "equiv", - "safe", - "same_kind", - "unsafe", - ], - ) + @testing.for_castings() @testing.for_all_dtypes_combination(names=["dtype1", "dtype2"]) @testing.numpy_cupy_array_equal( accept_error=(TypeError, numpy.ComplexWarning) @@ -537,7 +517,6 @@ def test_stack_dtype(self, xp, dtype1, dtype2): def test_stack_casting(self, xp, dtype1, dtype2, casting): a = testing.shaped_arange((3, 4), xp, dtype1) b = testing.shaped_arange((3, 4), xp, dtype1) - # may raise TypeError or ComplexWarning return xp.stack((a, b), dtype=dtype2, casting=casting) @pytest.mark.skip("dpnp.row_stack() is not implemented yet") From 3d21f51d4cb67f795dfe07ea831494f1d5356e39 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 7 Aug 2023 14:38:21 +0200 Subject: [PATCH 2/2] Relaxed check in a test of SYCL queue to account the error of floating operations --- tests/test_sycl_queue.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index 7dc15a6bccf..6cc3cce50d1 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -100,7 +100,7 @@ def test_array_creation(func, arg, kwargs, device): dpnp_kwargs["device"] = device dpnp_array = getattr(dpnp, func)(*arg, **dpnp_kwargs) - numpy.testing.assert_array_equal(numpy_array, dpnp_array) + assert_allclose(numpy_array, dpnp_array) assert dpnp_array.sycl_device == device @@ -125,7 +125,7 @@ def test_empty(device): ids=[device.filter_string for device in valid_devices], ) def test_empty_like(device_x, device_y): - x = dpnp.ndarray([1, 2, 3], device=device_x) + x = dpnp.array([1, 2, 3], device=device_x) y = dpnp.empty_like(x) assert_sycl_queue_equal(y.sycl_queue, x.sycl_queue) y = dpnp.empty_like(x, device=device_y) @@ -158,7 +158,7 @@ def test_array_creation_follow_device(func, args, kwargs, device): dpnp_args = [eval(val, {"x0": x}) for val in args] y = getattr(dpnp, func)(*dpnp_args, **kwargs) - numpy.testing.assert_allclose(y_orig, y) + assert_allclose(y_orig, y) assert_sycl_queue_equal(y.sycl_queue, x.sycl_queue) @@ -197,7 +197,7 @@ def test_array_creation_cross_device(func, args, kwargs, device_x, device_y): dpnp_kwargs["device"] = device_y y = getattr(dpnp, func)(*dpnp_args, **dpnp_kwargs) - numpy.testing.assert_allclose(y_orig, y) + assert_allclose(y_orig, y) assert_sycl_queue_equal(y.sycl_queue, x.to_device(device_y).sycl_queue) @@ -382,7 +382,7 @@ def test_broadcasting(func, data1, data2, device): x2 = dpnp.array(data2, device=device) result = getattr(dpnp, func)(x1, x2) - numpy.testing.assert_array_equal(result, expected) + assert_array_equal(result, expected) expected_queue = x1.get_array().sycl_queue result_queue = result.get_array().sycl_queue @@ -623,8 +623,8 @@ def test_modf(device): x = dpnp.array(data, device=device) result1, result2 = dpnp.modf(x) - numpy.testing.assert_array_equal(result1, expected1) - numpy.testing.assert_array_equal(result2, expected2) + assert_array_equal(result1, expected1) + assert_array_equal(result2, expected2) expected_queue = x.get_array().sycl_queue result1_queue = result1.get_array().sycl_queue @@ -648,7 +648,7 @@ def test_fft(type, device): expected = numpy.fft.fft(data) result = dpnp.fft.fft(dpnp_data) - numpy.testing.assert_allclose(result, expected, rtol=1e-4, atol=1e-7) + assert_allclose(result, expected, rtol=1e-4, atol=1e-7) expected_queue = dpnp_data.get_array().sycl_queue result_queue = result.get_array().sycl_queue @@ -690,7 +690,7 @@ def test_cholesky(device): result = dpnp.linalg.cholesky(dpnp_data) expected = numpy.linalg.cholesky(numpy_data) - numpy.testing.assert_array_equal(expected, result) + assert_array_equal(expected, result) expected_queue = dpnp_data.get_array().sycl_queue result_queue = result.get_array().sycl_queue @@ -710,7 +710,7 @@ def test_det(device): result = dpnp.linalg.det(dpnp_data) expected = numpy.linalg.det(numpy_data) - numpy.testing.assert_allclose(expected, result) + assert_allclose(expected, result) expected_queue = dpnp_data.get_array().sycl_queue result_queue = result.get_array().sycl_queue @@ -755,8 +755,8 @@ def test_eig(device): if numpy_vec[0, i] * dpnp_vec[0, i] < 0: numpy_vec[:, i] = -numpy_vec[:, i] - numpy.testing.assert_allclose(dpnp_val, numpy_val, rtol=1e-05, atol=1e-05) - numpy.testing.assert_allclose(dpnp_vec, numpy_vec, rtol=1e-05, atol=1e-05) + assert_allclose(dpnp_val, numpy_val, rtol=1e-05, atol=1e-05) + assert_allclose(dpnp_vec, numpy_vec, rtol=1e-05, atol=1e-05) assert dpnp_val.dtype == numpy_val.dtype assert dpnp_vec.dtype == numpy_vec.dtype @@ -827,7 +827,7 @@ def test_eigvals(device): result = dpnp.linalg.eigvals(dpnp_data) expected = numpy.linalg.eigvals(numpy_data) - numpy.testing.assert_allclose(expected, result, atol=0.5) + assert_allclose(expected, result, atol=0.5) expected_queue = dpnp_data.get_array().sycl_queue result_queue = result.get_array().sycl_queue @@ -847,7 +847,7 @@ def test_inv(device): result = dpnp.linalg.inv(dpnp_data) expected = numpy.linalg.inv(numpy_data) - numpy.testing.assert_allclose(expected, result) + assert_allclose(expected, result) expected_queue = dpnp_data.get_array().sycl_queue result_queue = result.get_array().sycl_queue @@ -867,7 +867,7 @@ def test_matrix_rank(device): result = dpnp.linalg.matrix_rank(dpnp_data) expected = numpy.linalg.matrix_rank(numpy_data) - numpy.testing.assert_array_equal(expected, result) + assert_array_equal(expected, result) @pytest.mark.parametrize( @@ -889,8 +889,8 @@ def test_qr(device): assert dpnp_q.shape == np_q.shape assert dpnp_r.shape == np_r.shape - numpy.testing.assert_allclose(dpnp_q, np_q, rtol=tol, atol=tol) - numpy.testing.assert_allclose(dpnp_r, np_r, rtol=tol, atol=tol) + assert_allclose(dpnp_q, np_q, rtol=tol, atol=tol) + assert_allclose(dpnp_r, np_r, rtol=tol, atol=tol) expected_queue = dpnp_data.get_array().sycl_queue dpnp_q_queue = dpnp_q.get_array().sycl_queue @@ -927,7 +927,7 @@ def test_svd(device): dpnp_diag_s[i, i] = dpnp_s[i] # check decomposition - numpy.testing.assert_allclose( + assert_allclose( dpnp_data, dpnp.dot(dpnp_u, dpnp.dot(dpnp_diag_s, dpnp_vt)), rtol=tol, @@ -941,10 +941,10 @@ def test_svd(device): # compare vectors for non-zero values for i in range(numpy.count_nonzero(np_s > tol)): - numpy.testing.assert_allclose( + assert_allclose( dpnp.asnumpy(dpnp_u)[:, i], np_u[:, i], rtol=tol, atol=tol ) - numpy.testing.assert_allclose( + assert_allclose( dpnp.asnumpy(dpnp_vt)[i, :], np_vt[i, :], rtol=tol, atol=tol )