From aef6de3d36c5594986408626ab04d7811d0b5144 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Thu, 18 May 2023 20:37:14 -0500 Subject: [PATCH 1/6] out keyword for elementwise functions --- dpctl/tensor/_elementwise_common.py | 246 ++++++++++++++++------- dpctl/tests/elementwise/test_abs.py | 17 ++ dpctl/tests/elementwise/test_add.py | 77 +++++++ dpctl/tests/elementwise/test_cos.py | 61 ++++++ dpctl/tests/elementwise/test_isfinite.py | 35 ++++ dpctl/tests/elementwise/test_isnan.py | 35 ++++ 6 files changed, 395 insertions(+), 76 deletions(-) diff --git a/dpctl/tensor/_elementwise_common.py b/dpctl/tensor/_elementwise_common.py index 46837ab1df..e7d1d2ca41 100644 --- a/dpctl/tensor/_elementwise_common.py +++ b/dpctl/tensor/_elementwise_common.py @@ -47,9 +47,33 @@ def __init__(self, name, result_type_resolver_fn, unary_dp_impl_fn, docs): self.unary_fn_ = unary_dp_impl_fn self.__doc__ = docs - def __call__(self, x, order="K"): + def __call__(self, x, out=None, order="K"): if not isinstance(x, dpt.usm_ndarray): raise TypeError(f"Expected dpctl.tensor.usm_ndarray, got {type(x)}") + + if out is not None: + if not isinstance(out, dpt.usm_ndarray): + raise TypeError( + f"output array must be of usm_ndarray type, got {type(out)}" + ) + + if out.shape != x.shape: + raise TypeError( + "The shape of input and output arrays are inconsistent." + f"Expected output shape is {x.shape}, got {out.shape}" + ) + + if ti._array_overlap(x, out): + raise TypeError("Input and output arrays have memory overlap") + + if ( + dpctl.utils.get_execution_queue((x.sycl_queue, out.sycl_queue)) + is None + ): + raise TypeError( + "Input and output allocation queues are not compatible" + ) + if order not in ["C", "F", "K", "A"]: order = "K" buf_dt, res_dt = _find_buf_dtype( @@ -59,17 +83,24 @@ def __call__(self, x, order="K"): raise RuntimeError exec_q = x.sycl_queue if buf_dt is None: - if order == "K": - r = _empty_like_orderK(x, res_dt) + if out is None: + if order == "K": + out = _empty_like_orderK(x, res_dt) + else: + if order == "A": + order = "F" if x.flags.f_contiguous else "C" + out = dpt.empty_like(x, dtype=res_dt, order=order) else: - if order == "A": - order = "F" if x.flags.f_contiguous else "C" - r = dpt.empty_like(x, dtype=res_dt, order=order) + if res_dt != out.dtype: + raise TypeError( + f"Expected output array of type {res_dt} is supported" + f", got {out.dtype}" + ) - ht, _ = self.unary_fn_(x, r, sycl_queue=exec_q) + ht, _ = self.unary_fn_(x, out, sycl_queue=exec_q) ht.wait() - return r + return out if order == "K": buf = _empty_like_orderK(x, buf_dt) else: @@ -80,16 +111,23 @@ def __call__(self, x, order="K"): ht_copy_ev, copy_ev = ti._copy_usm_ndarray_into_usm_ndarray( src=x, dst=buf, sycl_queue=exec_q ) - if order == "K": - r = _empty_like_orderK(buf, res_dt) + if out is None: + if order == "K": + out = _empty_like_orderK(buf, res_dt) + else: + out = dpt.empty_like(buf, dtype=res_dt, order=order) else: - r = dpt.empty_like(buf, dtype=res_dt, order=order) + if buf_dt != out.dtype: + raise TypeError( + f"Expected output array of type {buf_dt} is supported," + f"got {out.dtype}" + ) - ht, _ = self.unary_fn_(buf, r, sycl_queue=exec_q, depends=[copy_ev]) + ht, _ = self.unary_fn_(buf, out, sycl_queue=exec_q, depends=[copy_ev]) ht_copy_ev.wait() ht.wait() - return r + return out def _get_queue_usm_type(o): @@ -281,7 +319,7 @@ def __str__(self): def __repr__(self): return f"" - def __call__(self, o1, o2, order="K"): + def __call__(self, o1, o2, out=None, order="K"): if order not in ["K", "C", "F", "A"]: order = "K" q1, o1_usm_type = _get_queue_usm_type(o1) @@ -358,6 +396,31 @@ def __call__(self, o1, o2, order="K"): "supported types according to the casting rule ''safe''." ) + if out is not None: + if not isinstance(out, dpt.usm_ndarray): + raise TypeError( + f"output array must be of usm_ndarray type, got {type(out)}" + ) + + if out.shape != o1_shape or out.shape != o2_shape: + raise TypeError( + "The shape of input and output arrays are inconsistent." + f"Expected output shape is {o1_shape}, got {out.shape}" + ) + + if ti._array_overlap(o1, out) or ti._array_overlap(o2, out): + raise TypeError("Input and output arrays have memory overlap") + + if ( + dpctl.utils.get_execution_queue( + (o1.sycl_queue, o2.sycl_queue, out.sycl_queue) + ) + is None + ): + raise TypeError( + "Input and output allocation queues are not compatible" + ) + if isinstance(o1, dpt.usm_ndarray): src1 = o1 else: @@ -368,37 +431,45 @@ def __call__(self, o1, o2, order="K"): src2 = dpt.asarray(o2, dtype=o2_dtype, sycl_queue=exec_q) if buf1_dt is None and buf2_dt is None: - if order == "K": - r = _empty_like_pair_orderK( - src1, src2, res_dt, res_usm_type, exec_q - ) - else: - if order == "A": - order = ( - "F" - if all( - arr.flags.f_contiguous - for arr in ( - src1, - src2, + if out is None: + if order == "K": + out = _empty_like_pair_orderK( + src1, src2, res_dt, res_usm_type, exec_q + ) + else: + if order == "A": + order = ( + "F" + if all( + arr.flags.f_contiguous + for arr in ( + src1, + src2, + ) ) + else "C" ) - else "C" + out = dpt.empty( + res_shape, + dtype=res_dt, + usm_type=res_usm_type, + sycl_queue=exec_q, + order=order, ) - r = dpt.empty( - res_shape, - dtype=res_dt, - usm_type=res_usm_type, - sycl_queue=exec_q, - order=order, - ) + else: + if res_dt != out.dtype: + raise TypeError( + f"Output array of type {res_dt} is needed," + f"got {out.dtype}" + ) + src1 = dpt.broadcast_to(src1, res_shape) src2 = dpt.broadcast_to(src2, res_shape) ht_, _ = self.binary_fn_( - src1=src1, src2=src2, dst=r, sycl_queue=exec_q + src1=src1, src2=src2, dst=out, sycl_queue=exec_q ) ht_.wait() - return r + return out elif buf1_dt is None: if order == "K": buf2 = _empty_like_orderK(src2, buf2_dt) @@ -409,30 +480,38 @@ def __call__(self, o1, o2, order="K"): ht_copy_ev, copy_ev = ti._copy_usm_ndarray_into_usm_ndarray( src=src2, dst=buf2, sycl_queue=exec_q ) - if order == "K": - r = _empty_like_pair_orderK( - src1, buf2, res_dt, res_usm_type, exec_q - ) + if out is None: + if order == "K": + out = _empty_like_pair_orderK( + src1, buf2, res_dt, res_usm_type, exec_q + ) + else: + out = dpt.empty( + res_shape, + dtype=res_dt, + usm_type=res_usm_type, + sycl_queue=exec_q, + order=order, + ) else: - r = dpt.empty( - res_shape, - dtype=res_dt, - usm_type=res_usm_type, - sycl_queue=exec_q, - order=order, - ) + if res_dt != out.dtype: + raise TypeError( + f"Output array of type {res_dt} is needed," + f"got {out.dtype}" + ) + src1 = dpt.broadcast_to(src1, res_shape) buf2 = dpt.broadcast_to(buf2, res_shape) ht_, _ = self.binary_fn_( src1=src1, src2=buf2, - dst=r, + dst=out, sycl_queue=exec_q, depends=[copy_ev], ) ht_copy_ev.wait() ht_.wait() - return r + return out elif buf2_dt is None: if order == "K": buf1 = _empty_like_orderK(src1, buf1_dt) @@ -443,30 +522,38 @@ def __call__(self, o1, o2, order="K"): ht_copy_ev, copy_ev = ti._copy_usm_ndarray_into_usm_ndarray( src=src1, dst=buf1, sycl_queue=exec_q ) - if order == "K": - r = _empty_like_pair_orderK( - buf1, src2, res_dt, res_usm_type, exec_q - ) + if out is None: + if order == "K": + out = _empty_like_pair_orderK( + buf1, src2, res_dt, res_usm_type, exec_q + ) + else: + out = dpt.empty( + res_shape, + dtype=res_dt, + usm_type=res_usm_type, + sycl_queue=exec_q, + order=order, + ) else: - r = dpt.empty( - res_shape, - dtype=res_dt, - usm_type=res_usm_type, - sycl_queue=exec_q, - order=order, - ) + if res_dt != out.dtype: + raise TypeError( + f"Output array of type {res_dt} is needed," + f"got {out.dtype}" + ) + buf1 = dpt.broadcast_to(buf1, res_shape) src2 = dpt.broadcast_to(src2, res_shape) ht_, _ = self.binary_fn_( src1=buf1, src2=src2, - dst=r, + dst=out, sycl_queue=exec_q, depends=[copy_ev], ) ht_copy_ev.wait() ht_.wait() - return r + return out if order in ["K", "A"]: if src1.flags.f_contiguous and src2.flags.f_contiguous: @@ -489,26 +576,33 @@ def __call__(self, o1, o2, order="K"): ht_copy2_ev, copy2_ev = ti._copy_usm_ndarray_into_usm_ndarray( src=src2, dst=buf2, sycl_queue=exec_q ) - if order == "K": - r = _empty_like_pair_orderK( - buf1, buf2, res_dt, res_usm_type, exec_q - ) + if out is None: + if order == "K": + out = _empty_like_pair_orderK( + buf1, buf2, res_dt, res_usm_type, exec_q + ) + else: + out = dpt.empty( + res_shape, + dtype=res_dt, + usm_type=res_usm_type, + sycl_queue=exec_q, + order=order, + ) else: - r = dpt.empty( - res_shape, - dtype=res_dt, - usm_type=res_usm_type, - sycl_queue=exec_q, - order=order, - ) + if res_dt != out.dtype: + raise TypeError( + f"Output array of type {res_dt} is needed, got {out.dtype}" + ) + buf1 = dpt.broadcast_to(buf1, res_shape) buf2 = dpt.broadcast_to(buf2, res_shape) ht_, _ = self.binary_fn_( src1=buf1, src2=buf2, - dst=r, + dst=out, sycl_queue=exec_q, depends=[copy1_ev, copy2_ev], ) dpctl.SyclEvent.wait_for([ht_copy1_ev, ht_copy2_ev, ht_]) - return r + return out diff --git a/dpctl/tests/elementwise/test_abs.py b/dpctl/tests/elementwise/test_abs.py index 275be0d573..94bc05d918 100644 --- a/dpctl/tests/elementwise/test_abs.py +++ b/dpctl/tests/elementwise/test_abs.py @@ -89,3 +89,20 @@ def test_abs_complex(dtype): np.testing.assert_allclose( dpt.asnumpy(Y), expected_Y, atol=tol, rtol=tol ) + + +@pytest.mark.parametrize("dtype", _all_dtypes[:-2]) +def test_abs_out_keyword(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + arg_dt = np.dtype(dtype) + input_shape = (10, 10, 10, 10) + X = dpt.empty(input_shape, dtype=arg_dt, sycl_queue=q) + X[..., 0::2] = 1 + X[..., 1::2] = 0 + Y = dpt.empty_like(X, dtype=arg_dt) + dpt.abs(X, Y) + + expected_Y = dpt.asnumpy(X) + assert np.allclose(dpt.asnumpy(Y), expected_Y) diff --git a/dpctl/tests/elementwise/test_add.py b/dpctl/tests/elementwise/test_add.py index 81176f4f45..95104a7441 100644 --- a/dpctl/tests/elementwise/test_add.py +++ b/dpctl/tests/elementwise/test_add.py @@ -2,6 +2,7 @@ import numpy as np import pytest +from numpy.testing import assert_raises_regex import dpctl import dpctl.tensor as dpt @@ -165,3 +166,79 @@ def __sycl_usm_array_interface__(self): c = Canary() with pytest.raises(ValueError): dpt.add(a, c) + + +@pytest.mark.parametrize("op1_dtype", _all_dtypes) +@pytest.mark.parametrize("op2_dtype", _all_dtypes) +def test_add_dtype_out_keyword(op1_dtype, op2_dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(op1_dtype, q) + skip_if_dtype_not_supported(op2_dtype, q) + + sz = 127 + ar1 = dpt.ones(sz, dtype=op1_dtype) + ar2 = dpt.ones_like(ar1, dtype=op2_dtype) + + r = dpt.add(ar1, ar2) + + y = dpt.zeros_like(ar1, dtype=r.dtype) + dpt.add(ar1, ar2, y) + + assert np.array_equal(dpt.asnumpy(r), dpt.asnumpy(y)) + + +def test_add_errors(): + ar1 = dpt.ones(2, dtype="float32", device="gpu") + ar2 = dpt.ones_like(ar1, dtype="int32", device="gpu") + y = dpt.empty_like(ar1, device="cpu") + assert_raises_regex( + TypeError, + "Input and output allocation queues are not compatible", + dpt.add, + ar1, + ar2, + y, + ) + + ar1 = dpt.ones(2, dtype="float32") + ar2 = dpt.ones_like(ar1, dtype="int32") + y = dpt.empty(3) + assert_raises_regex( + TypeError, + "The shape of input and output arrays are inconsistent", + dpt.add, + ar1, + ar2, + y, + ) + + ar1 = dpt.ones(2, dtype="float32") + ar2 = dpt.ones_like(ar1, dtype="int32") + y = ar1 + assert_raises_regex( + TypeError, + "Input and output arrays have memory overlap", + dpt.add, + ar1, + ar2, + y, + ) + + ar1 = dpt.ones(2, dtype="float32") + ar2 = dpt.ones_like(ar1, dtype="int32") + y = dpt.empty_like(ar1, dtype="int32") + assert_raises_regex( + TypeError, "Output array of type.*is needed", dpt.add, ar1, ar2, y + ) + + ar1 = dpt.ones(2, dtype="float32") + ar2 = dpt.ones_like(ar1, dtype="int32") + y = np.empty_like(ar1) + assert_raises_regex( + TypeError, + "output array must be of usm_ndarray type", + dpt.add, + ar1, + ar2, + y, + ) diff --git a/dpctl/tests/elementwise/test_cos.py b/dpctl/tests/elementwise/test_cos.py index 22588aea44..9397261596 100644 --- a/dpctl/tests/elementwise/test_cos.py +++ b/dpctl/tests/elementwise/test_cos.py @@ -2,6 +2,7 @@ import numpy as np import pytest +from numpy.testing import assert_raises_regex import dpctl.tensor as dpt from dpctl.tests.helper import get_queue_or_skip, skip_if_dtype_not_supported @@ -85,3 +86,63 @@ def test_cos_order(dtype): np.testing.assert_allclose( dpt.asnumpy(Y), expected_Y, atol=tol, rtol=tol ) + + +@pytest.mark.parametrize("dtype", ["f2", "f4", "f8", "c8", "c16"]) +def test_cos_out_keyword(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + n_seq = 100 + n_rep = 137 + + Xnp = np.linspace(-np.pi / 4, np.pi / 4, num=n_seq, dtype=dtype) + X = dpt.asarray(np.repeat(Xnp, n_rep), dtype=dtype, sycl_queue=q) + Y = dpt.empty_like(X, dtype=dtype) + + dpt.cos(X, Y) + tol = 8 * dpt.finfo(Y.dtype).resolution + + np.testing.assert_allclose( + dpt.asnumpy(Y), np.repeat(np.cos(Xnp), n_rep), atol=tol, rtol=tol + ) + + +def test_cos_errors(): + x = dpt.zeros(2, device="gpu") + y = dpt.empty_like(x, device="cpu") + assert_raises_regex( + TypeError, + "Input and output allocation queues are not compatible", + dpt.cos, + x, + y, + ) + + x = dpt.zeros(2) + y = dpt.empty(3) + assert_raises_regex( + TypeError, + "The shape of input and output arrays are inconsistent", + dpt.cos, + x, + y, + ) + + x = dpt.zeros(2) + y = x + assert_raises_regex( + TypeError, "Input and output arrays have memory overlap", dpt.cos, x, y + ) + + x = dpt.zeros(2, dtype="int32") + y = dpt.empty_like(x, dtype="int32") + assert_raises_regex( + TypeError, "Expected output array of type.*is supported", dpt.cos, x, y + ) + + x = dpt.zeros(2, dtype="float32") + y = np.empty_like(x) + assert_raises_regex( + TypeError, "output array must be of usm_ndarray type", dpt.cos, x, y + ) diff --git a/dpctl/tests/elementwise/test_isfinite.py b/dpctl/tests/elementwise/test_isfinite.py index 5cc9699cf8..fa3150fc4f 100644 --- a/dpctl/tests/elementwise/test_isfinite.py +++ b/dpctl/tests/elementwise/test_isfinite.py @@ -72,3 +72,38 @@ def test_isfinite_order(dtype): Y = dpt.isfinite(U, order=ord) expected_Y = np.full(Y.shape, True, dtype=Y.dtype) assert np.allclose(dpt.asnumpy(Y), expected_Y) + + +@pytest.mark.parametrize("dtype", ["c8", "c16"]) +def test_isnan_complex_out_keyword(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + y1 = complex(np.nan, np.nan) + y2 = complex(1, np.nan) + y3 = complex(np.nan, 1) + y4 = complex(2, 1) + y5 = complex(np.inf, 1) + + Ynp = np.repeat(np.array([y1, y2, y3, y4, y5], dtype=dtype), 12) + Y = dpt.asarray(Ynp, sycl_queue=q) + out = dpt.empty_like(Y, dtype="bool") + dpt.isfinite(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) + + +@pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) +def test_isfinite_floats_out_keyword(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + y1 = np.nan + y2 = 1 + y3 = np.inf + + for mult in [123, 137, 255, 271, 272]: + Ynp = np.repeat(np.array([y1, y2, y3], dtype=dtype), mult) + Y = dpt.asarray(Ynp, sycl_queue=q) + out = dpt.empty_like(Y, dtype="bool") + dpt.isfinite(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) diff --git a/dpctl/tests/elementwise/test_isnan.py b/dpctl/tests/elementwise/test_isnan.py index 8e983cb2dc..0796f0f0f8 100644 --- a/dpctl/tests/elementwise/test_isnan.py +++ b/dpctl/tests/elementwise/test_isnan.py @@ -72,3 +72,38 @@ def test_isnan_order(dtype): Y = dpt.isnan(U, order=ord) expected_Y = np.full(Y.shape, False, dtype=Y.dtype) assert np.allclose(dpt.asnumpy(Y), expected_Y) + + +@pytest.mark.parametrize("dtype", ["c8", "c16"]) +def test_isnan_complex_out_keyword(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + y1 = complex(np.nan, np.nan) + y2 = complex(1, np.nan) + y3 = complex(np.nan, 1) + y4 = complex(2, 1) + y5 = complex(np.inf, 1) + + Ynp = np.repeat(np.array([y1, y2, y3, y4, y5], dtype=dtype), 123) + Y = dpt.asarray(Ynp, sycl_queue=q) + out = dpt.empty_like(Y, dtype="bool") + dpt.isnan(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) + + +@pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) +def test_isnan_floats_out_keyword(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + y1 = np.nan + y2 = 1 + y3 = np.inf + + for mult in [123, 137, 255, 271, 272]: + Ynp = np.repeat(np.array([y1, y2, y3], dtype=dtype), mult) + Y = dpt.asarray(Ynp, sycl_queue=q) + out = dpt.empty_like(Y, dtype="bool") + dpt.isnan(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) From 21e14158cfe49c8257fa550224a9bd226926cb3a Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Thu, 18 May 2023 22:05:10 -0500 Subject: [PATCH 2/6] update the tests --- dpctl/tensor/_elementwise_common.py | 2 +- dpctl/tests/elementwise/test_add.py | 27 ++++++++++++++++++++++++--- dpctl/tests/elementwise/test_cos.py | 14 ++++++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/dpctl/tensor/_elementwise_common.py b/dpctl/tensor/_elementwise_common.py index e7d1d2ca41..d78e5fe2b2 100644 --- a/dpctl/tensor/_elementwise_common.py +++ b/dpctl/tensor/_elementwise_common.py @@ -402,7 +402,7 @@ def __call__(self, o1, o2, out=None, order="K"): f"output array must be of usm_ndarray type, got {type(out)}" ) - if out.shape != o1_shape or out.shape != o2_shape: + if out.shape != res_shape: raise TypeError( "The shape of input and output arrays are inconsistent." f"Expected output shape is {o1_shape}, got {out.shape}" diff --git a/dpctl/tests/elementwise/test_add.py b/dpctl/tests/elementwise/test_add.py index 95104a7441..ee0a311546 100644 --- a/dpctl/tests/elementwise/test_add.py +++ b/dpctl/tests/elementwise/test_add.py @@ -111,6 +111,18 @@ def test_add_broadcasting(): r2 = dpt.add(v, m) assert (dpt.asnumpy(r2) == np.arange(1, 6, dtype="i4")[np.newaxis, :]).all() + out = dpt.empty_like(m) + dpt.add(m, v, out) + assert ( + dpt.asnumpy(out) == np.arange(1, 6, dtype="i4")[np.newaxis, :] + ).all() + + out2 = dpt.empty_like(m) + dpt.add(v, m, out2) + assert ( + dpt.asnumpy(out2) == np.arange(1, 6, dtype="i4")[np.newaxis, :] + ).all() + @pytest.mark.parametrize("arr_dt", _all_dtypes) def test_add_python_scalar(arr_dt): @@ -188,9 +200,18 @@ def test_add_dtype_out_keyword(op1_dtype, op2_dtype): def test_add_errors(): - ar1 = dpt.ones(2, dtype="float32", device="gpu") - ar2 = dpt.ones_like(ar1, dtype="int32", device="gpu") - y = dpt.empty_like(ar1, device="cpu") + try: + gpu_queue = dpctl.SyclQueue("gpu") + except dpctl.SyclQueueCreationError: + pytest.skip("SyclQueue('gpu') failed, skipping") + try: + cpu_queue = dpctl.SyclQueue("cpu") + except dpctl.SyclQueueCreationError: + pytest.skip("SyclQueue('cpu') failed, skipping") + + ar1 = dpt.ones(2, dtype="float32", sycl_queue=gpu_queue) + ar2 = dpt.ones_like(ar1, sycl_queue=gpu_queue) + y = dpt.empty_like(ar1, sycl_queue=cpu_queue) assert_raises_regex( TypeError, "Input and output allocation queues are not compatible", diff --git a/dpctl/tests/elementwise/test_cos.py b/dpctl/tests/elementwise/test_cos.py index 9397261596..b8fff07bd9 100644 --- a/dpctl/tests/elementwise/test_cos.py +++ b/dpctl/tests/elementwise/test_cos.py @@ -4,6 +4,7 @@ import pytest from numpy.testing import assert_raises_regex +import dpctl import dpctl.tensor as dpt from dpctl.tests.helper import get_queue_or_skip, skip_if_dtype_not_supported @@ -109,8 +110,17 @@ def test_cos_out_keyword(dtype): def test_cos_errors(): - x = dpt.zeros(2, device="gpu") - y = dpt.empty_like(x, device="cpu") + try: + gpu_queue = dpctl.SyclQueue("gpu") + except dpctl.SyclQueueCreationError: + pytest.skip("SyclQueue('gpu') failed, skipping") + try: + cpu_queue = dpctl.SyclQueue("cpu") + except dpctl.SyclQueueCreationError: + pytest.skip("SyclQueue('cpu') failed, skipping") + + x = dpt.zeros(2, sycl_queue=gpu_queue) + y = dpt.empty_like(x, sycl_queue=cpu_queue) assert_raises_regex( TypeError, "Input and output allocation queues are not compatible", From 121f819be41909f2a634b2dbe8307e6bf9de0408 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 19 May 2023 19:54:55 -0500 Subject: [PATCH 3/6] add new tests to improve coverage --- dpctl/tensor/_elementwise_common.py | 7 ++- dpctl/tests/elementwise/test_abs.py | 25 ++++------- dpctl/tests/elementwise/test_add.py | 57 ++++++++++++++---------- dpctl/tests/elementwise/test_cos.py | 53 +++++++++++----------- dpctl/tests/elementwise/test_isfinite.py | 43 ++++-------------- dpctl/tests/elementwise/test_isnan.py | 43 ++++-------------- 6 files changed, 87 insertions(+), 141 deletions(-) diff --git a/dpctl/tensor/_elementwise_common.py b/dpctl/tensor/_elementwise_common.py index d78e5fe2b2..6677670e73 100644 --- a/dpctl/tensor/_elementwise_common.py +++ b/dpctl/tensor/_elementwise_common.py @@ -93,8 +93,8 @@ def __call__(self, x, out=None, order="K"): else: if res_dt != out.dtype: raise TypeError( - f"Expected output array of type {res_dt} is supported" - f", got {out.dtype}" + f"Output array of type {res_dt} is needed," + f" got {out.dtype}" ) ht, _ = self.unary_fn_(x, out, sycl_queue=exec_q) @@ -119,8 +119,7 @@ def __call__(self, x, out=None, order="K"): else: if buf_dt != out.dtype: raise TypeError( - f"Expected output array of type {buf_dt} is supported," - f"got {out.dtype}" + f"Output array of type {buf_dt} is needed, got {out.dtype}" ) ht, _ = self.unary_fn_(buf, out, sycl_queue=exec_q, depends=[copy_ev]) diff --git a/dpctl/tests/elementwise/test_abs.py b/dpctl/tests/elementwise/test_abs.py index 94bc05d918..2e2ff69ea4 100644 --- a/dpctl/tests/elementwise/test_abs.py +++ b/dpctl/tests/elementwise/test_abs.py @@ -22,9 +22,17 @@ def test_abs_out_type(dtype): np.dtype("c16"): np.dtype("f8"), } assert dpt.abs(X).dtype == type_map[arg_dt] + + out = dpt.empty_like(X, dtype=type_map[arg_dt]) + dpt.abs(X, out) + assert np.allclose(dpt.asnumpy(out), dpt.asnumpy(dpt.abs(X))) else: assert dpt.abs(X).dtype == arg_dt + out = dpt.empty_like(X, dtype=arg_dt) + dpt.abs(X, out) + assert np.allclose(dpt.asnumpy(out), dpt.asnumpy(dpt.abs(X))) + @pytest.mark.parametrize("usm_type", _usm_types) def test_abs_usm_type(usm_type): @@ -89,20 +97,3 @@ def test_abs_complex(dtype): np.testing.assert_allclose( dpt.asnumpy(Y), expected_Y, atol=tol, rtol=tol ) - - -@pytest.mark.parametrize("dtype", _all_dtypes[:-2]) -def test_abs_out_keyword(dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(dtype, q) - - arg_dt = np.dtype(dtype) - input_shape = (10, 10, 10, 10) - X = dpt.empty(input_shape, dtype=arg_dt, sycl_queue=q) - X[..., 0::2] = 1 - X[..., 1::2] = 0 - Y = dpt.empty_like(X, dtype=arg_dt) - dpt.abs(X, Y) - - expected_Y = dpt.asnumpy(X) - assert np.allclose(dpt.asnumpy(Y), expected_Y) diff --git a/dpctl/tests/elementwise/test_add.py b/dpctl/tests/elementwise/test_add.py index ee0a311546..8a17b4f761 100644 --- a/dpctl/tests/elementwise/test_add.py +++ b/dpctl/tests/elementwise/test_add.py @@ -7,6 +7,7 @@ import dpctl import dpctl.tensor as dpt from dpctl.tests.helper import get_queue_or_skip, skip_if_dtype_not_supported +from dpctl.utils import ExecutionPlacementError from .utils import _all_dtypes, _compare_dtypes, _usm_types @@ -32,6 +33,10 @@ def test_add_dtype_matrix(op1_dtype, op2_dtype): assert (dpt.asnumpy(r) == np.full(r.shape, 2, dtype=r.dtype)).all() assert r.sycl_queue == ar1.sycl_queue + out = dpt.empty_like(ar1, dtype=expected_dtype) + dpt.add(ar1, ar2, out) + assert (dpt.asnumpy(out) == np.full(out.shape, 2, dtype=out.dtype)).all() + ar3 = dpt.ones(sz, dtype=op1_dtype) ar4 = dpt.ones(2 * sz, dtype=op2_dtype) @@ -44,6 +49,10 @@ def test_add_dtype_matrix(op1_dtype, op2_dtype): assert r.shape == ar3.shape assert (dpt.asnumpy(r) == np.full(r.shape, 2, dtype=r.dtype)).all() + out = dpt.empty_like(ar1, dtype=expected_dtype) + dpt.add(ar3[::-1], ar4[::2], out) + assert (dpt.asnumpy(out) == np.full(out.shape, 2, dtype=out.dtype)).all() + @pytest.mark.parametrize("op1_usm_type", _usm_types) @pytest.mark.parametrize("op2_usm_type", _usm_types) @@ -105,7 +114,6 @@ def test_add_broadcasting(): v = dpt.arange(5, dtype="i4") r = dpt.add(m, v) - assert (dpt.asnumpy(r) == np.arange(1, 6, dtype="i4")[np.newaxis, :]).all() r2 = dpt.add(v, m) @@ -180,26 +188,8 @@ def __sycl_usm_array_interface__(self): dpt.add(a, c) -@pytest.mark.parametrize("op1_dtype", _all_dtypes) -@pytest.mark.parametrize("op2_dtype", _all_dtypes) -def test_add_dtype_out_keyword(op1_dtype, op2_dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(op1_dtype, q) - skip_if_dtype_not_supported(op2_dtype, q) - - sz = 127 - ar1 = dpt.ones(sz, dtype=op1_dtype) - ar2 = dpt.ones_like(ar1, dtype=op2_dtype) - - r = dpt.add(ar1, ar2) - - y = dpt.zeros_like(ar1, dtype=r.dtype) - dpt.add(ar1, ar2, y) - - assert np.array_equal(dpt.asnumpy(r), dpt.asnumpy(y)) - - def test_add_errors(): + get_queue_or_skip() try: gpu_queue = dpctl.SyclQueue("gpu") except dpctl.SyclQueueCreationError: @@ -245,11 +235,14 @@ def test_add_errors(): y, ) - ar1 = dpt.ones(2, dtype="float32") - ar2 = dpt.ones_like(ar1, dtype="int32") - y = dpt.empty_like(ar1, dtype="int32") + ar1 = np.ones(2, dtype="float32") + ar2 = np.ones_like(ar1, dtype="int32") assert_raises_regex( - TypeError, "Output array of type.*is needed", dpt.add, ar1, ar2, y + ExecutionPlacementError, + "Execution placement can not be unambiguously inferred.*", + dpt.add, + ar1, + ar2, ) ar1 = dpt.ones(2, dtype="float32") @@ -263,3 +256,19 @@ def test_add_errors(): ar2, y, ) + + +@pytest.mark.parametrize("dtype", _all_dtypes) +def test_add_dtype_error( + dtype, +): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + ar1 = dpt.ones(5, dtype=dtype) + ar2 = dpt.ones_like(ar1, dtype="f8") + + y = dpt.zeros_like(ar1, dtype="int8") + assert_raises_regex( + TypeError, "Output array of type.*is needed", dpt.add, ar1, ar2, y + ) diff --git a/dpctl/tests/elementwise/test_cos.py b/dpctl/tests/elementwise/test_cos.py index b8fff07bd9..0d1e641b5f 100644 --- a/dpctl/tests/elementwise/test_cos.py +++ b/dpctl/tests/elementwise/test_cos.py @@ -21,6 +21,13 @@ def test_cos_out_type(dtype): expected_dtype = _map_to_device_dtype(expected_dtype, q.sycl_device) assert dpt.cos(X).dtype == expected_dtype + X = dpt.asarray(0, dtype=dtype, sycl_queue=q) + expected_dtype = np.cos(np.array(0, dtype=dtype)).dtype + expected_dtype = _map_to_device_dtype(expected_dtype, q.sycl_device) + Y = dpt.empty_like(X, dtype=expected_dtype) + dpt.cos(X, Y) + np.testing.assert_allclose(dpt.asnumpy(dpt.cos(X)), dpt.asnumpy(Y)) + @pytest.mark.parametrize("dtype", ["f2", "f4", "f8", "c8", "c16"]) def test_cos_output(dtype): @@ -40,6 +47,13 @@ def test_cos_output(dtype): dpt.asnumpy(Y), np.repeat(np.cos(Xnp), n_rep), atol=tol, rtol=tol ) + Z = dpt.empty_like(X, dtype=dtype) + dpt.cos(X, Z) + + np.testing.assert_allclose( + dpt.asnumpy(Z), np.repeat(np.cos(Xnp), n_rep), atol=tol, rtol=tol + ) + @pytest.mark.parametrize("usm_type", ["device", "shared", "host"]) def test_cos_usm_type(usm_type): @@ -89,27 +103,8 @@ def test_cos_order(dtype): ) -@pytest.mark.parametrize("dtype", ["f2", "f4", "f8", "c8", "c16"]) -def test_cos_out_keyword(dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(dtype, q) - - n_seq = 100 - n_rep = 137 - - Xnp = np.linspace(-np.pi / 4, np.pi / 4, num=n_seq, dtype=dtype) - X = dpt.asarray(np.repeat(Xnp, n_rep), dtype=dtype, sycl_queue=q) - Y = dpt.empty_like(X, dtype=dtype) - - dpt.cos(X, Y) - tol = 8 * dpt.finfo(Y.dtype).resolution - - np.testing.assert_allclose( - dpt.asnumpy(Y), np.repeat(np.cos(Xnp), n_rep), atol=tol, rtol=tol - ) - - def test_cos_errors(): + get_queue_or_skip() try: gpu_queue = dpctl.SyclQueue("gpu") except dpctl.SyclQueueCreationError: @@ -145,14 +140,20 @@ def test_cos_errors(): TypeError, "Input and output arrays have memory overlap", dpt.cos, x, y ) - x = dpt.zeros(2, dtype="int32") - y = dpt.empty_like(x, dtype="int32") - assert_raises_regex( - TypeError, "Expected output array of type.*is supported", dpt.cos, x, y - ) - x = dpt.zeros(2, dtype="float32") y = np.empty_like(x) assert_raises_regex( TypeError, "output array must be of usm_ndarray type", dpt.cos, x, y ) + + +@pytest.mark.parametrize("dtype", _all_dtypes) +def test_cos_error_dtype(dtype): + q = get_queue_or_skip() + skip_if_dtype_not_supported(dtype, q) + + x = dpt.zeros(5, dtype=dtype) + y = dpt.empty_like(x, dtype="int16") + assert_raises_regex( + TypeError, "Output array of type.*is needed", dpt.cos, x, y + ) diff --git a/dpctl/tests/elementwise/test_isfinite.py b/dpctl/tests/elementwise/test_isfinite.py index fa3150fc4f..7f86277c07 100644 --- a/dpctl/tests/elementwise/test_isfinite.py +++ b/dpctl/tests/elementwise/test_isfinite.py @@ -41,6 +41,10 @@ def test_isfinite_complex(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isfinite(Y)), np.isfinite(Ynp)) + out = dpt.empty_like(Y, dtype="bool") + dpt.isfinite(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) + @pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) def test_isfinite_floats(dtype): @@ -56,6 +60,10 @@ def test_isfinite_floats(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isfinite(Y)), np.isfinite(Ynp)) + out = dpt.empty_like(Y, dtype="bool") + dpt.isfinite(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) + @pytest.mark.parametrize("dtype", _all_dtypes) def test_isfinite_order(dtype): @@ -72,38 +80,3 @@ def test_isfinite_order(dtype): Y = dpt.isfinite(U, order=ord) expected_Y = np.full(Y.shape, True, dtype=Y.dtype) assert np.allclose(dpt.asnumpy(Y), expected_Y) - - -@pytest.mark.parametrize("dtype", ["c8", "c16"]) -def test_isnan_complex_out_keyword(dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(dtype, q) - - y1 = complex(np.nan, np.nan) - y2 = complex(1, np.nan) - y3 = complex(np.nan, 1) - y4 = complex(2, 1) - y5 = complex(np.inf, 1) - - Ynp = np.repeat(np.array([y1, y2, y3, y4, y5], dtype=dtype), 12) - Y = dpt.asarray(Ynp, sycl_queue=q) - out = dpt.empty_like(Y, dtype="bool") - dpt.isfinite(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) - - -@pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) -def test_isfinite_floats_out_keyword(dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(dtype, q) - - y1 = np.nan - y2 = 1 - y3 = np.inf - - for mult in [123, 137, 255, 271, 272]: - Ynp = np.repeat(np.array([y1, y2, y3], dtype=dtype), mult) - Y = dpt.asarray(Ynp, sycl_queue=q) - out = dpt.empty_like(Y, dtype="bool") - dpt.isfinite(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) diff --git a/dpctl/tests/elementwise/test_isnan.py b/dpctl/tests/elementwise/test_isnan.py index 0796f0f0f8..74d922b6db 100644 --- a/dpctl/tests/elementwise/test_isnan.py +++ b/dpctl/tests/elementwise/test_isnan.py @@ -41,6 +41,10 @@ def test_isnan_complex(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isnan(Y)), np.isnan(Ynp)) + out = dpt.empty_like(Y, dtype="bool") + dpt.isnan(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) + @pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) def test_isnan_floats(dtype): @@ -56,6 +60,10 @@ def test_isnan_floats(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isnan(Y)), np.isnan(Ynp)) + out = dpt.empty_like(Y, dtype="bool") + dpt.isnan(Y, out) + assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) + @pytest.mark.parametrize("dtype", _all_dtypes) def test_isnan_order(dtype): @@ -72,38 +80,3 @@ def test_isnan_order(dtype): Y = dpt.isnan(U, order=ord) expected_Y = np.full(Y.shape, False, dtype=Y.dtype) assert np.allclose(dpt.asnumpy(Y), expected_Y) - - -@pytest.mark.parametrize("dtype", ["c8", "c16"]) -def test_isnan_complex_out_keyword(dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(dtype, q) - - y1 = complex(np.nan, np.nan) - y2 = complex(1, np.nan) - y3 = complex(np.nan, 1) - y4 = complex(2, 1) - y5 = complex(np.inf, 1) - - Ynp = np.repeat(np.array([y1, y2, y3, y4, y5], dtype=dtype), 123) - Y = dpt.asarray(Ynp, sycl_queue=q) - out = dpt.empty_like(Y, dtype="bool") - dpt.isnan(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) - - -@pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) -def test_isnan_floats_out_keyword(dtype): - q = get_queue_or_skip() - skip_if_dtype_not_supported(dtype, q) - - y1 = np.nan - y2 = 1 - y3 = np.inf - - for mult in [123, 137, 255, 271, 272]: - Ynp = np.repeat(np.array([y1, y2, y3], dtype=dtype), mult) - Y = dpt.asarray(Ynp, sycl_queue=q) - out = dpt.empty_like(Y, dtype="bool") - dpt.isnan(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) From 05ae945382ca1515ea40ff1c655629f4afbf57d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Sat, 20 May 2023 11:11:07 -0500 Subject: [PATCH 4/6] Fixed tests to run on Iris Xe Also ensure that test_add_order exercises non-same dtypes to improve coverage. --- dpctl/tests/elementwise/test_add.py | 80 +++++++++++++++++------------ 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/dpctl/tests/elementwise/test_add.py b/dpctl/tests/elementwise/test_add.py index 8a17b4f761..586c78eab2 100644 --- a/dpctl/tests/elementwise/test_add.py +++ b/dpctl/tests/elementwise/test_add.py @@ -33,7 +33,7 @@ def test_add_dtype_matrix(op1_dtype, op2_dtype): assert (dpt.asnumpy(r) == np.full(r.shape, 2, dtype=r.dtype)).all() assert r.sycl_queue == ar1.sycl_queue - out = dpt.empty_like(ar1, dtype=expected_dtype) + out = dpt.empty_like(ar1, dtype=r.dtype) dpt.add(ar1, ar2, out) assert (dpt.asnumpy(out) == np.full(out.shape, 2, dtype=out.dtype)).all() @@ -49,7 +49,7 @@ def test_add_dtype_matrix(op1_dtype, op2_dtype): assert r.shape == ar3.shape assert (dpt.asnumpy(r) == np.full(r.shape, 2, dtype=r.dtype)).all() - out = dpt.empty_like(ar1, dtype=expected_dtype) + out = dpt.empty_like(ar1, dtype=r.dtype) dpt.add(ar3[::-1], ar4[::2], out) assert (dpt.asnumpy(out) == np.full(out.shape, 2, dtype=out.dtype)).all() @@ -74,37 +74,49 @@ def test_add_usm_type_matrix(op1_usm_type, op2_usm_type): def test_add_order(): get_queue_or_skip() - ar1 = dpt.ones((20, 20), dtype="i4", order="C") - ar2 = dpt.ones((20, 20), dtype="i4", order="C") - r1 = dpt.add(ar1, ar2, order="C") - assert r1.flags.c_contiguous - r2 = dpt.add(ar1, ar2, order="F") - assert r2.flags.f_contiguous - r3 = dpt.add(ar1, ar2, order="A") - assert r3.flags.c_contiguous - r4 = dpt.add(ar1, ar2, order="K") - assert r4.flags.c_contiguous - - ar1 = dpt.ones((20, 20), dtype="i4", order="F") - ar2 = dpt.ones((20, 20), dtype="i4", order="F") - r1 = dpt.add(ar1, ar2, order="C") - assert r1.flags.c_contiguous - r2 = dpt.add(ar1, ar2, order="F") - assert r2.flags.f_contiguous - r3 = dpt.add(ar1, ar2, order="A") - assert r3.flags.f_contiguous - r4 = dpt.add(ar1, ar2, order="K") - assert r4.flags.f_contiguous - - ar1 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2] - ar2 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2] - r4 = dpt.add(ar1, ar2, order="K") - assert r4.strides == (20, -1) - - ar1 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2].mT - ar2 = dpt.ones((40, 40), dtype="i4", order="C")[:20, ::-2].mT - r4 = dpt.add(ar1, ar2, order="K") - assert r4.strides == (-1, 20) + test_shape = ( + 20, + 20, + ) + test_shape2 = tuple(2 * dim for dim in test_shape) + n = test_shape[-1] + + for dt1, dt2 in zip(["i4", "i4", "f4"], ["i4", "f4", "i4"]): + ar1 = dpt.ones(test_shape, dtype=dt1, order="C") + ar2 = dpt.ones(test_shape, dtype=dt2, order="C") + r1 = dpt.add(ar1, ar2, order="C") + assert r1.flags.c_contiguous + r2 = dpt.add(ar1, ar2, order="F") + assert r2.flags.f_contiguous + r3 = dpt.add(ar1, ar2, order="A") + assert r3.flags.c_contiguous + r4 = dpt.add(ar1, ar2, order="K") + assert r4.flags.c_contiguous + + ar1 = dpt.ones(test_shape, dtype=dt1, order="F") + ar2 = dpt.ones(test_shape, dtype=dt2, order="F") + r1 = dpt.add(ar1, ar2, order="C") + assert r1.flags.c_contiguous + r2 = dpt.add(ar1, ar2, order="F") + assert r2.flags.f_contiguous + r3 = dpt.add(ar1, ar2, order="A") + assert r3.flags.f_contiguous + r4 = dpt.add(ar1, ar2, order="K") + assert r4.flags.f_contiguous + + ar1 = dpt.ones(test_shape2, dtype=dt1, order="C")[:20, ::-2] + ar2 = dpt.ones(test_shape2, dtype=dt2, order="C")[:20, ::-2] + r4 = dpt.add(ar1, ar2, order="K") + assert r4.strides == (n, -1) + r5 = dpt.add(ar1, ar2, order="C") + assert r5.strides == (n, 1) + + ar1 = dpt.ones(test_shape2, dtype=dt1, order="C")[:20, ::-2].mT + ar2 = dpt.ones(test_shape2, dtype=dt2, order="C")[:20, ::-2].mT + r4 = dpt.add(ar1, ar2, order="K") + assert r4.strides == (-1, n) + r5 = dpt.add(ar1, ar2, order="C") + assert r5.strides == (n, 1) def test_add_broadcasting(): @@ -266,7 +278,7 @@ def test_add_dtype_error( skip_if_dtype_not_supported(dtype, q) ar1 = dpt.ones(5, dtype=dtype) - ar2 = dpt.ones_like(ar1, dtype="f8") + ar2 = dpt.ones_like(ar1, dtype="f4") y = dpt.zeros_like(ar1, dtype="int8") assert_raises_regex( From d691846f34cd153ecaea6d7423ef70719e7fe64f Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Sat, 20 May 2023 11:21:47 -0500 Subject: [PATCH 5/6] Added a test for broadcasting error --- dpctl/tests/elementwise/test_add.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dpctl/tests/elementwise/test_add.py b/dpctl/tests/elementwise/test_add.py index 586c78eab2..b8d202c54f 100644 --- a/dpctl/tests/elementwise/test_add.py +++ b/dpctl/tests/elementwise/test_add.py @@ -144,6 +144,14 @@ def test_add_broadcasting(): ).all() +def test_add_broadcasting_error(): + get_queue_or_skip() + m = dpt.ones((10, 10), dtype="i4") + v = dpt.ones((3,), dtype="i4") + with pytest.raises(ValueError): + dpt.add(m, v) + + @pytest.mark.parametrize("arr_dt", _all_dtypes) def test_add_python_scalar(arr_dt): q = get_queue_or_skip() From f3d5519d55a3c8dbb79dfa6620c84346bf445f9d Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Sat, 20 May 2023 13:26:10 -0500 Subject: [PATCH 6/6] use keywrod argument --- dpctl/tests/elementwise/test_abs.py | 12 +++++----- dpctl/tests/elementwise/test_add.py | 30 ++++++++++-------------- dpctl/tests/elementwise/test_cos.py | 4 ++-- dpctl/tests/elementwise/test_isfinite.py | 12 +++++----- dpctl/tests/elementwise/test_isnan.py | 12 +++++----- 5 files changed, 33 insertions(+), 37 deletions(-) diff --git a/dpctl/tests/elementwise/test_abs.py b/dpctl/tests/elementwise/test_abs.py index 2e2ff69ea4..d4aefaf76d 100644 --- a/dpctl/tests/elementwise/test_abs.py +++ b/dpctl/tests/elementwise/test_abs.py @@ -23,15 +23,15 @@ def test_abs_out_type(dtype): } assert dpt.abs(X).dtype == type_map[arg_dt] - out = dpt.empty_like(X, dtype=type_map[arg_dt]) - dpt.abs(X, out) - assert np.allclose(dpt.asnumpy(out), dpt.asnumpy(dpt.abs(X))) + r = dpt.empty_like(X, dtype=type_map[arg_dt]) + dpt.abs(X, out=r) + assert np.allclose(dpt.asnumpy(r), dpt.asnumpy(dpt.abs(X))) else: assert dpt.abs(X).dtype == arg_dt - out = dpt.empty_like(X, dtype=arg_dt) - dpt.abs(X, out) - assert np.allclose(dpt.asnumpy(out), dpt.asnumpy(dpt.abs(X))) + r = dpt.empty_like(X, dtype=arg_dt) + dpt.abs(X, out=r) + assert np.allclose(dpt.asnumpy(r), dpt.asnumpy(dpt.abs(X))) @pytest.mark.parametrize("usm_type", _usm_types) diff --git a/dpctl/tests/elementwise/test_add.py b/dpctl/tests/elementwise/test_add.py index b8d202c54f..2b4ab8e3cb 100644 --- a/dpctl/tests/elementwise/test_add.py +++ b/dpctl/tests/elementwise/test_add.py @@ -33,9 +33,9 @@ def test_add_dtype_matrix(op1_dtype, op2_dtype): assert (dpt.asnumpy(r) == np.full(r.shape, 2, dtype=r.dtype)).all() assert r.sycl_queue == ar1.sycl_queue - out = dpt.empty_like(ar1, dtype=r.dtype) - dpt.add(ar1, ar2, out) - assert (dpt.asnumpy(out) == np.full(out.shape, 2, dtype=out.dtype)).all() + r2 = dpt.empty_like(ar1, dtype=r.dtype) + dpt.add(ar1, ar2, out=r2) + assert (dpt.asnumpy(r2) == np.full(r2.shape, 2, dtype=r2.dtype)).all() ar3 = dpt.ones(sz, dtype=op1_dtype) ar4 = dpt.ones(2 * sz, dtype=op2_dtype) @@ -49,9 +49,9 @@ def test_add_dtype_matrix(op1_dtype, op2_dtype): assert r.shape == ar3.shape assert (dpt.asnumpy(r) == np.full(r.shape, 2, dtype=r.dtype)).all() - out = dpt.empty_like(ar1, dtype=r.dtype) - dpt.add(ar3[::-1], ar4[::2], out) - assert (dpt.asnumpy(out) == np.full(out.shape, 2, dtype=out.dtype)).all() + r2 = dpt.empty_like(ar1, dtype=r.dtype) + dpt.add(ar3[::-1], ar4[::2], out=r2) + assert (dpt.asnumpy(r2) == np.full(r2.shape, 2, dtype=r2.dtype)).all() @pytest.mark.parametrize("op1_usm_type", _usm_types) @@ -131,17 +131,13 @@ def test_add_broadcasting(): r2 = dpt.add(v, m) assert (dpt.asnumpy(r2) == np.arange(1, 6, dtype="i4")[np.newaxis, :]).all() - out = dpt.empty_like(m) - dpt.add(m, v, out) - assert ( - dpt.asnumpy(out) == np.arange(1, 6, dtype="i4")[np.newaxis, :] - ).all() - - out2 = dpt.empty_like(m) - dpt.add(v, m, out2) - assert ( - dpt.asnumpy(out2) == np.arange(1, 6, dtype="i4")[np.newaxis, :] - ).all() + r3 = dpt.empty_like(m) + dpt.add(m, v, out=r3) + assert (dpt.asnumpy(r3) == np.arange(1, 6, dtype="i4")[np.newaxis, :]).all() + + r4 = dpt.empty_like(m) + dpt.add(v, m, out=r4) + assert (dpt.asnumpy(r4) == np.arange(1, 6, dtype="i4")[np.newaxis, :]).all() def test_add_broadcasting_error(): diff --git a/dpctl/tests/elementwise/test_cos.py b/dpctl/tests/elementwise/test_cos.py index 0d1e641b5f..395fa60435 100644 --- a/dpctl/tests/elementwise/test_cos.py +++ b/dpctl/tests/elementwise/test_cos.py @@ -25,7 +25,7 @@ def test_cos_out_type(dtype): expected_dtype = np.cos(np.array(0, dtype=dtype)).dtype expected_dtype = _map_to_device_dtype(expected_dtype, q.sycl_device) Y = dpt.empty_like(X, dtype=expected_dtype) - dpt.cos(X, Y) + dpt.cos(X, out=Y) np.testing.assert_allclose(dpt.asnumpy(dpt.cos(X)), dpt.asnumpy(Y)) @@ -48,7 +48,7 @@ def test_cos_output(dtype): ) Z = dpt.empty_like(X, dtype=dtype) - dpt.cos(X, Z) + dpt.cos(X, out=Z) np.testing.assert_allclose( dpt.asnumpy(Z), np.repeat(np.cos(Xnp), n_rep), atol=tol, rtol=tol diff --git a/dpctl/tests/elementwise/test_isfinite.py b/dpctl/tests/elementwise/test_isfinite.py index 7f86277c07..92e585d217 100644 --- a/dpctl/tests/elementwise/test_isfinite.py +++ b/dpctl/tests/elementwise/test_isfinite.py @@ -41,9 +41,9 @@ def test_isfinite_complex(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isfinite(Y)), np.isfinite(Ynp)) - out = dpt.empty_like(Y, dtype="bool") - dpt.isfinite(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) + r = dpt.empty_like(Y, dtype="bool") + dpt.isfinite(Y, out=r) + assert np.array_equal(dpt.asnumpy(r)[()], np.isfinite(Ynp)) @pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) @@ -60,9 +60,9 @@ def test_isfinite_floats(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isfinite(Y)), np.isfinite(Ynp)) - out = dpt.empty_like(Y, dtype="bool") - dpt.isfinite(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isfinite(Ynp)) + r = dpt.empty_like(Y, dtype="bool") + dpt.isfinite(Y, out=r) + assert np.array_equal(dpt.asnumpy(r)[()], np.isfinite(Ynp)) @pytest.mark.parametrize("dtype", _all_dtypes) diff --git a/dpctl/tests/elementwise/test_isnan.py b/dpctl/tests/elementwise/test_isnan.py index 74d922b6db..7545251bf2 100644 --- a/dpctl/tests/elementwise/test_isnan.py +++ b/dpctl/tests/elementwise/test_isnan.py @@ -41,9 +41,9 @@ def test_isnan_complex(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isnan(Y)), np.isnan(Ynp)) - out = dpt.empty_like(Y, dtype="bool") - dpt.isnan(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) + r = dpt.empty_like(Y, dtype="bool") + dpt.isnan(Y, out=r) + assert np.array_equal(dpt.asnumpy(r)[()], np.isnan(Ynp)) @pytest.mark.parametrize("dtype", ["f2", "f4", "f8"]) @@ -60,9 +60,9 @@ def test_isnan_floats(dtype): Y = dpt.asarray(Ynp, sycl_queue=q) assert np.array_equal(dpt.asnumpy(dpt.isnan(Y)), np.isnan(Ynp)) - out = dpt.empty_like(Y, dtype="bool") - dpt.isnan(Y, out) - assert np.array_equal(dpt.asnumpy(out)[()], np.isnan(Ynp)) + r = dpt.empty_like(Y, dtype="bool") + dpt.isnan(Y, out=r) + assert np.array_equal(dpt.asnumpy(r)[()], np.isnan(Ynp)) @pytest.mark.parametrize("dtype", _all_dtypes)