【快乐开源】Paddle Tensor规范化第二期 0-size tensor 支持copysign
本文最后更新于 2024-12-11,文章内容可能已经过时。
copysign
copysign-API文档-PaddlePaddle深度学习平台
问题复现
ARRAY_API_TESTS_MODULE=array_api_compat.paddle ARRAY_API_TESTS_SKIP_DTYPES=int8,int16,uint16,uint8,uint32,uint64 ARRAY_API_TESTS_VERSION="2023.12" python -m pytest -s -vvv 'array_api_tests/test_operators_and_elementwise_functions.py::test_copysign'
执行结果如下:
============================================= FAILURES =============================================
__________________________________________ test_copysign ___________________________________________
+ Exception Group Traceback (most recent call last):
| File "/usr/local/lib/python3.9/dist-packages/_pytest/runner.py", line 341, in from_call
| result: Optional[TResult] = func()
| File "/usr/local/lib/python3.9/dist-packages/_pytest/runner.py", line 262, in <lambda>
| lambda: ihook(item=item, **kwds), when=when, reraise=reraise
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_hooks.py", line 493, in __call__
| return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_manager.py", line 115, in _hookexec
| return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_callers.py", line 152, in _multicall
| return outcome.get_result()
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_result.py", line 114, in get_result
| raise exc.with_traceback(exc.__traceback__)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_callers.py", line 77, in _multicall
| res = hook_impl.function(*args)
| File "/usr/local/lib/python3.9/dist-packages/_pytest/runner.py", line 177, in pytest_runtest_call
| raise e
| File "/usr/local/lib/python3.9/dist-packages/_pytest/runner.py", line 169, in pytest_runtest_call
| item.runtest()
| File "/usr/local/lib/python3.9/dist-packages/_pytest/python.py", line 1792, in runtest
| self.ihook.pytest_pyfunc_call(pyfuncitem=self)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_hooks.py", line 493, in __call__
| return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_manager.py", line 115, in _hookexec
| return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_callers.py", line 113, in _multicall
| raise exception.with_traceback(exception.__traceback__)
| File "/usr/local/lib/python3.9/dist-packages/pluggy/_callers.py", line 77, in _multicall
| res = hook_impl.function(*args)
| File "/usr/local/lib/python3.9/dist-packages/_pytest/python.py", line 194, in pytest_pyfunc_call
| result = testfunction(**testargs)
| File "/home/Paddle/array-api-tests/array_api_tests/test_operators_and_elementwise_functions.py", line 1064, in test_copysign
| @given(*hh.two_mutual_arrays(dh.real_float_dtypes))
| File "/usr/local/lib/python3.9/dist-packages/hypothesis/core.py", line 1722, in wrapped_test
| raise the_error_hypothesis_found
| exceptiongroup.ExceptionGroup: Hypothesis found 2 distinct failures. (2 sub-exceptions)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/home/Paddle/array-api-tests/array_api_tests/test_operators_and_elementwise_functions.py", line 1066, in test_copysign
| out = xp.copysign(x1, x2)
| File "/home/Paddle/array-api-compat/array_api_compat/paddle/_aliases.py", line 82, in _f
| return f(x1, x2, **kwargs)
| File "/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py", line 8007, in copysign
| return _C_ops.copysign(x, y)
| ValueError: (InvalidArgument) The type of data we are trying to retrieve (float64) does not match the type of data (float32) currently contained in the container.
| [Hint: Expected dtype() == phi::CppTypeToDataType<T>::Type(), but received dtype():10 != phi::CppTypeToDataType<T>::Type():11.] (at /home/Paddle/paddle/phi/core/dense_tensor.cc:153)
|
| Falsifying example: test_copysign(
| x1=Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
| 0.),
| x2=Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
| 0.), # or any other generated value
| )
+---------------- 2 ----------------
| Traceback (most recent call last):
| File "/home/Paddle/array-api-tests/array_api_tests/test_operators_and_elementwise_functions.py", line 1066, in test_copysign
| out = xp.copysign(x1, x2)
| File "/home/Paddle/array-api-compat/array_api_compat/paddle/_aliases.py", line 82, in _f
| return f(x1, x2, **kwargs)
| File "/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py", line 8007, in copysign
| return _C_ops.copysign(x, y)
| RuntimeError: (PreconditionNotMet) The meta data must be valid when call the mutable data function.
| [Hint: Expected valid() == true, but received valid():0 != true:1.] (at /home/Paddle/paddle/phi/core/dense_tensor.cc:113)
|
| Falsifying example: test_copysign(
| x1=Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
| 0.),
| x2=Tensor(shape=[0], dtype=float32, place=Place(cpu), stop_gradient=True,
| []),
| )
| Explanation:
| These lines were always and only run by failing examples:
| /home/Paddle/array-api-compat/array_api_compat/paddle/_aliases.py:865
| /usr/local/lib/python3.9/dist-packages/paddle/base/dygraph/tensor_patch_methods.py:584
| /usr/local/lib/python3.9/dist-packages/paddle/base/dygraph/tensor_patch_methods.py:781
| /usr/local/lib/python3.9/dist-packages/paddle/base/dygraph/tensor_patch_methods.py:790
| /usr/local/lib/python3.9/dist-packages/paddle/base/framework.py:1630
| (and 4 more with settings.verbosity >= verbose)
+------------------------------------
========================================= warnings summary =========================================
array_api_tests/__init__.py:83
/home/Paddle/array-api-tests/array_api_tests/__init__.py:83: HypothesisWarning: Could not determine whether module array_api_compat.paddle is an Array API library
xps = array_api.make_strategies_namespace(xp, api_version=api_version)
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py:8002: UserWarning: The shape of broadcast output [1, 1, 1, -1, 3] is different from the input tensor x with shape: [0, 3], please make sure you are using copysign api correctly.
warnings.warn(
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py:8002: UserWarning: The shape of broadcast output [1, 1, 3, 1, 1] is different from the input tensor x with shape: [1, 1, 1, 1, 1], please make sure you are using copysign api correctly.
warnings.warn(
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py:8002: UserWarning: The shape of broadcast output [-1, 3] is different from the input tensor x with shape: [0, 3], please make sure you are using copysign api correctly.
warnings.warn(
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py:8002: UserWarning: The shape of broadcast output [3] is different from the input tensor x with shape: [], please make sure you are using copysign api correctly.
warnings.warn(
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py:8002: UserWarning: The shape of broadcast output [1] is different from the input tensor x with shape: [], please make sure you are using copysign api correctly.
warnings.warn(
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
array_api_tests/test_operators_and_elementwise_functions.py::test_copysign
/usr/local/lib/python3.9/dist-packages/paddle/tensor/math.py:8002: UserWarning: The shape of broadcast output [-1] is different from the input tensor x with shape: [], please make sure you are using copysign api correctly.
warnings.warn(
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
===================================== short test summary info ======================================
FAILED array_api_tests/test_operators_and_elementwise_functions.py::test_copysign - exceptiongroup.ExceptionGroup: Hypothesis found 2 distinct failures. (2 sub-exceptions)
================================= 1 failed, 21 warnings in 32.94s ==================================
问题1:api-test源码问题
测试时没有指定两个input类型一致
只需要在测试代码中指定类型一致即可
array_api_tests/test_operators_and_elementwise_functions.py
@pytest.mark.min_version("2023.12")
@given(*hh.two_mutual_arrays(dh.real_float_dtypes))
def test_copysign(x1, x2):
x1 = x1.astype('float64')
x2 = x2.astype('float64')
out = xp.copysign(x1, x2)
ph.assert_dtype("copysign", in_dtype=[x1.dtype, x2.dtype], out_dtype=out.dtype)
ph.assert_result_shape("copysign", in_shapes=[x1.shape, x2.shape], out_shape=tuple(out.shape))
binary_assert_against_refimpl("copysign", x1, x2, out, math.copysign)
问题2:需要支持0-size
这个不需要修改kernel,只需在python层修改
python/paddle/tensor/math.py
def copysign(x: Tensor, y: Tensor | float, name: str | None = None) -> Tensor:
r"""
Create a new floating-point tensor with the magnitude of input ``x`` and the sign of ``y``, elementwise.
Equation:
.. math::
copysign(x_{i},y_{i})=\left\{\begin{matrix}
& -|x_{i}| & if \space y_{i} <= -0.0\\
& |x_{i}| & if \space y_{i} >= 0.0
\end{matrix}\right.
Args:
x (Tensor): The input Tensor, magnitudes, the data type is bool, uint8, int8, int16, int32, int64, bfloat16, float16, float32, float64.
y (Tensor|float): contains value(s) whose signbit(s) are applied to the magnitudes in input.
name (str|None, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
Returns:
out (Tensor), the output tensor. The data type is the same as the input tensor.
Examples:
.. code-block:: python
:name: example1
>>> import paddle
>>> x = paddle.to_tensor([1, 2, 3], dtype='float64')
>>> y = paddle.to_tensor([-1, 1, -1], dtype='float64')
>>> out = paddle.copysign(x, y)
>>> print(out)
Tensor(shape=[3], dtype=float64, place=Place(gpu:0), stop_gradient=True,
[-1., 2., -3.])
.. code-block:: python
:name: example2
>>> import paddle
>>> x = paddle.to_tensor([1, 2, 3], dtype='float64')
>>> y = paddle.to_tensor([-2], dtype='float64')
>>> res = paddle.copysign(x, y)
>>> print(res)
Tensor(shape=[3], dtype=float64, place=Place(gpu:0), stop_gradient=True,
[-1., -2., -3.])
.. code-block:: python
:name: example_zero1
>>> import paddle
>>> x = paddle.to_tensor([1, 2, 3], dtype='float64')
>>> y = paddle.to_tensor([0.0], dtype='float64')
>>> out = paddle.copysign(x, y)
>>> print(out)
Tensor(shape=[3], dtype=float64, place=Place(gpu:0), stop_gradient=True,
[1., 2., 3.])
.. code-block:: python
:name: example_zero2
>>> import paddle
>>> x = paddle.to_tensor([1, 2, 3], dtype='float64')
>>> y = paddle.to_tensor([-0.0], dtype='float64')
>>> out = paddle.copysign(x, y)
>>> print(out)
Tensor(shape=[3], dtype=float64, place=Place(gpu:0), stop_gradient=True,
[-1., -2., -3.])
"""
if isinstance(y, (float, int)):
y = paddle.to_tensor(y, dtype=x.dtype)
if x.numel() == 0 or y.numel() == 0:
out_shape = paddle.broadcast_shape(x.shape, y.shape)
out_shape = [builtins.max(0, dim) for dim in out_shape]
return paddle.empty(shape=out_shape, dtype=x.dtype)
out_shape = broadcast_shape(x.shape, y.shape)
if out_shape != list(x.shape):
warnings.warn(
f"The shape of broadcast output {out_shape} is different from the input tensor x with shape: {x.shape}, please make sure you are using copysign api correctly."
)
if in_dynamic_or_pir_mode():
return _C_ops.copysign(x, y)
else:
helper = LayerHelper("copysign", **locals())
out = helper.create_variable_for_type_inference(dtype=x.dtype)
helper.append_op(
type='copysign', inputs={'x': x, 'y': y}, outputs={'out': out}
)
return out
增加了对x和y的形状判断,如果其中一个为0-size则返回0-size tensor
编译测试
cd /paddle/build
time cmake .. -DPY_VERSION=3.10 -DWITH_GPU=OFF -DWITH_TESTING=ON
time make -j$(nproc)
cd /paddle/build/python/dist
pip install -U paddlepaddle-0.0.0-cp310-cp310-linux_x86_64.whl --force-reinstall -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
添加单测
/test/legacy/test_copysign_op.py
暂时没有想明白静态图怎么在python里实现检测
class TestCopySignDygrapgZeroDimCase(unittest.TestCase):
def setUp(self):
self.input_init()
self.place_init()
def input_init(self):
dtype = np.float16
self.x = np.array(1.23, dtype=dtype)
self.y = np.empty([0], dtype=dtype)
def place_init(self):
self.place = (
paddle.CUDAPlace(0)
if paddle.is_compiled_with_cuda()
else paddle.CPUPlace()
)
def test_dygraph_api(self):
paddle.disable_static()
x = paddle.to_tensor(self.x)
y = paddle.to_tensor(self.y)
out = paddle.copysign(x, y)
out_ref = ref_copysign(self.x, self.y)
np.testing.assert_allclose(out_ref, out.numpy())
out_ref_dtype = out_ref.dtype
np.testing.assert_equal((out_ref_dtype == out.numpy().dtype), True)
paddle.enable_static()
pre-commit通过
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Moon
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果