Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d74db35
fix code style
Manfredss Nov 13, 2025
80d3ad9
add doc and signature for bitwise_xor_
Manfredss Nov 14, 2025
c7ed42b
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Nov 14, 2025
4ed899f
Sink bitwise_xor to cpp
Manfredss Nov 15, 2025
f6841d0
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Nov 15, 2025
9f92fbd
fix numpy func name error (no attribute '_bitwise_xor') and add type …
Manfredss Nov 16, 2025
4f01bbc
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Nov 16, 2025
6d385e6
fix static check and xpu test
Manfredss Nov 17, 2025
c9e9706
fix
Manfredss Nov 21, 2025
0f7b938
fix
Manfredss Nov 21, 2025
2b1b309
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Nov 25, 2025
e25e4da
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Nov 25, 2025
db3b1fb
fix: use cpp sink only
Manfredss Nov 26, 2025
d5240bf
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Nov 26, 2025
d3bab02
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Dec 3, 2025
38b750c
sunk bitwise_xor to cpp and add decorator for bitwise_xor_
Manfredss Dec 4, 2025
b7bf087
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Dec 4, 2025
a434bce
fix
Manfredss Dec 5, 2025
ea3d45e
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Dec 5, 2025
68d4666
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
Manfredss Dec 12, 2025
a34a8de
add signatures, add test for broadcast logic, test compat cases for b…
Manfredss Dec 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions paddle/phi/ops/yaml/python_api_info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@
args_alias:
use_default_mapping : True

- op : bitwise_xor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

下沉后原来的python 层API需要删掉,只有c++接口了

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#76341 (comment) 主要是这个问题,所以我还留着

Copy link
Contributor

@zhwesky2010 zhwesky2010 Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

把两个一起下沉了就行了

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的

name : [paddle.bitwise_xor, paddle.Tensor.bitwise_xor]
args_alias :
use_default_mapping : True

- op : bitwise_xor_
name : [paddle.bitwise_xor_, paddle.Tensor.bitwise_xor_]
args_alias :
use_default_mapping : True

- op : argmax
name : [paddle.argmax, paddle.Tensor.argmax]
args_mapper :
Expand Down
73 changes: 73 additions & 0 deletions python/paddle/_paddle_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3155,3 +3155,76 @@ def asin(
) -> Tensor
""",
)

add_doc_and_signature(
"bitwise_xor",
r"""

Apply ``bitwise_xor`` on Tensor ``X`` and ``Y`` .

.. math::
Out = X ^\wedge Y

Note:
``paddle.bitwise_xor`` supports broadcasting. If you want know more about broadcasting, please refer to please refer to `Introduction to Tensor`_ .

.. _Introduction to Tensor: ../../guides/beginner/tensor_en.html#chapter5-broadcasting-of-tensor

Args:
x (Tensor): Input Tensor of ``bitwise_xor`` . It is a N-D Tensor of bool, uint8, int8, int16, int32, int64.
Parameter alias: ``input``.
y (Tensor): Input Tensor of ``bitwise_xor`` . It is a N-D Tensor of bool, uint8, int8, int16, int32, int64.
Parameter alias: ``other``.
name (str|None, optional): The default value is None. Normally there is no need for
user to set this property. For more information, please refer to :ref:`api_guide_Name`.

Returns:
Tensor: Result of ``bitwise_xor`` . It is a N-D Tensor with the same data type of input Tensor.

Examples:
.. code-block:: python

>>> import paddle
>>> x = paddle.to_tensor([-5, -1, 1])
>>> y = paddle.to_tensor([4, 2, -3])
>>> # Using original parameter name
>>> res = paddle.bitwise_xor(x, y)
>>> print(res)
Tensor(shape=[3], dtype=int64, place=Place(cpu), stop_gradient=True,
[-1, -3, -4])

>>> # Using Pytorch-compatible parameter name
>>> res = paddle.bitwise_xor(input=x, other=y)
>>> print(res)
Tensor(shape=[3], dtype=int64, place=Place(cpu), stop_gradient=True,
[-1, -3, -4])
""",
"""
def bitwise_xor(
x: Tensor,
y: Tensor,
name: str | None = None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

签名统一参照其他的:

(x, y, name, *, out)

*,
out: Tensor | None = None,
) -> Tensor
""",
)

add_doc_and_signature(
"bitwise_xor_",
r"""
An inplace version of ``bitwise_xor``.

This API applies bitwise XOR between the elements of `x` and the corresponding elements of `y`,
modifies `x` in-place, and returns the modified `x`.
""",
"""
def bitwise_xor_(
x: Tensor,
y: Tensor,
name: str | None = None,
*,
out: Tensor | None = None,
) -> Tensor
""",
)
65 changes: 5 additions & 60 deletions python/paddle/tensor/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import paddle
from paddle import _C_ops
from paddle._C_ops import ( # noqa: F401
bitwise_xor,
bitwise_xor_,
greater_than,
isclose,
logical_and,
Expand Down Expand Up @@ -49,6 +51,7 @@
if TYPE_CHECKING:
from paddle import Tensor


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

下沉后,需要移除之前的python api,就没有这一层逻辑了。直接走c++

__all__ = []


Expand Down Expand Up @@ -1209,49 +1212,6 @@ def bitwise_or_(x: Tensor, y: Tensor, name: str | None = None) -> Tensor:
return _C_ops.bitwise_or_(x, y)


def bitwise_xor(
x: Tensor, y: Tensor, out: Tensor | None = None, name: str | None = None
) -> Tensor:
r"""

Apply ``bitwise_xor`` on Tensor ``X`` and ``Y`` .

.. math::
Out = X ^\wedge Y

Note:
``paddle.bitwise_xor`` supports broadcasting. If you want know more about broadcasting, please refer to please refer to `Introduction to Tensor`_ .

.. _Introduction to Tensor: ../../guides/beginner/tensor_en.html#chapter5-broadcasting-of-tensor

Args:
x (Tensor): Input Tensor of ``bitwise_xor`` . It is a N-D Tensor of bool, uint8, int8, int16, int32, int64.
y (Tensor): Input Tensor of ``bitwise_xor`` . It is a N-D Tensor of bool, uint8, int8, int16, int32, int64.
out (Tensor|None, optional): Result of ``bitwise_xor`` . It is a N-D Tensor with the same data type of input Tensor. Default: None.
name (str|None, optional): The default value is None. Normally there is no need for
user to set this property. For more information, please refer to :ref:`api_guide_Name`.

Returns:
Tensor: Result of ``bitwise_xor`` . It is a N-D Tensor with the same data type of input Tensor.

Examples:
.. code-block:: python

>>> import paddle
>>> x = paddle.to_tensor([-5, -1, 1])
>>> y = paddle.to_tensor([4, 2, -3])
>>> res = paddle.bitwise_xor(x, y)
>>> print(res)
Tensor(shape=[3], dtype=int64, place=Place(cpu), stop_gradient=True,
[-1, -3, -4])
"""
if in_dynamic_or_pir_mode() and out is None:
return _C_ops.bitwise_xor(x, y)
return _bitwise_op(
op_name="bitwise_xor", x=x, y=y, name=name, out=out, binary_op=True
)


def __rxor__(
x: Tensor,
y: int | bool,
Expand All @@ -1260,28 +1220,13 @@ def __rxor__(
) -> Tensor:
if isinstance(y, (int, bool)):
y = paddle.to_tensor(y, dtype=x.dtype)
return bitwise_xor(y, x, out=out, name=name)
return bitwise_xor(y, x, name=name, out=out)
else:
raise TypeError(
f"unsupported operand type(s) for |: '{type(y).__name__}' and 'Tensor'"
f"unsupported operand type(s) for ^: '{type(y).__name__}' and 'Tensor'"
)


@inplace_apis_in_dygraph_only
def bitwise_xor_(x: Tensor, y: Tensor, name: str | None = None) -> Tensor:
r"""
Inplace version of ``bitwise_xor`` API, the output Tensor will be inplaced with input ``x``.
Please refer to :ref:`api_paddle_bitwise_xor`.
"""
out_shape = broadcast_shape(x.shape, y.shape)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

下沉后,这个逻辑可能会丢掉了,需要测一下

if out_shape != x.shape:
raise ValueError(
f"The shape of broadcast output {out_shape} is different from that of inplace tensor {x.shape} in the Inplace operation."
)
if in_dynamic_mode():
return _C_ops.bitwise_xor_(x, y)


def bitwise_not(
x: Tensor, out: Tensor | None = None, name: str | None = None
) -> Tensor:
Expand Down
8 changes: 4 additions & 4 deletions test/legacy_test/test_bitwise_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ def init_data(self):
class TestBitwiseXor(OpTest):
def setUp(self):
self.op_type = "bitwise_xor"
self.python_api = paddle.tensor.logic.bitwise_xor
self.python_api = paddle.bitwise_xor

self.init_dtype()
self.init_shape()
Expand Down Expand Up @@ -653,7 +653,7 @@ def init_shape(self):
class TestBitwiseXorBool(TestBitwiseXor):
def setUp(self):
self.op_type = "bitwise_xor"
self.python_api = paddle.tensor.logic.bitwise_xor
self.python_api = paddle.bitwise_xor

self.init_shape()

Expand All @@ -674,8 +674,8 @@ class TestElementwiseBitwiseXorOp_Stride(OpTest):

def setUp(self):
self.op_type = "bitwise_xor"
self.python_api = paddle.tensor.logic.bitwise_xor
self.public_python_api = paddle.tensor.logic.bitwise_xor
self.python_api = paddle.bitwise_xor
self.public_python_api = paddle.bitwise_xor
self.transpose_api = paddle.transpose
self.as_stride_api = paddle.as_strided
self.init_dtype()
Expand Down
60 changes: 60 additions & 0 deletions test/legacy_test/test_inplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@

import functools
import unittest
import warnings

import numpy as np
from op_test import get_device_place, get_places, is_custom_device

import paddle

warnings.filterwarnings("ignore", category=UserWarning)


class TestInplace(unittest.TestCase):
def test_forward_version(self):
Expand Down Expand Up @@ -1547,12 +1550,69 @@ def non_inplace_api_processing(self, var):

class TestDygraphInplacBitwiseXor(TestDygraphInplacBitwiseAnd):
def inplace_api_processing(self, var):
out_shape = paddle.broadcast_shape(var.shape, self.y.shape)
if var.shape != out_shape:
raise ValueError(
f"The shape of broadcast output {out_shape} is different from that of inplace tensor {var.shape} in the Inplace operation."
)
return paddle.bitwise_xor_(var, self.y)

def non_inplace_api_processing(self, var):
return paddle.bitwise_xor(var, self.y)


class TestDygraphInplacBitwiseXorAlias1(TestDygraphInplacBitwiseAnd):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

paddle.bitwise_xor测一下compat情况下的用法

Copy link
Contributor Author

@Manfredss Manfredss Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bitwise_xor_ 需要吗?好像 bitwise_xor_ 用了 compat 会有 segfault 的情况,我认为可能是 bitwise_xor_ 下沉了但是 ops.yaml 里没有 bitwise_xor_ 的定义。需要添加吗?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bitwise_xor_ 需要吗?好像 bitwise_xor_ 用了 compat 会有 segfault 的情况,我认为可能是 bitwise_xor_ 下沉了但是 ops.yaml 里没有 bitwise_xor_ 的定义。需要添加吗?

ops.yaml里不需要bitwise_xor_定义,会根据bitwise_xor的inplace字段,来生成bitwise_xor_

两者本质是共享一个kernel的,只在输出out处理这里有些区别。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bitwise_xor_ 需要吗?好像 bitwise_xor_ 用了 compat 会有 segfault 的情况,我认为可能是 bitwise_xor_ 下沉了但是 ops.yaml 里没有 bitwise_xor_ 的定义。需要添加吗?

先按标准来测试,不要绕过,先提前暴露问题。
这里的segfault是不是触发了什么底层机制的问题?因为目前还没有inplace的API下沉过。

def inplace_api_processing(self, var):
out_shape = paddle.broadcast_shape(var.shape, self.y.shape)
if var.shape != out_shape:
raise ValueError(
f"The shape of broadcast output {out_shape} is different from that of inplace tensor {var.shape} in the Inplace operation."
)
return paddle.bitwise_xor_(var, self.y)

def non_inplace_api_processing(self, var):
return paddle.bitwise_xor(input=var, y=self.y)


class TestDygraphInplacBitwiseXorAlias2(TestDygraphInplacBitwiseAnd):
def inplace_api_processing(self, var):
out_shape = paddle.broadcast_shape(var.shape, self.y.shape)
if var.shape != out_shape:
raise ValueError(
f"The shape of broadcast output {out_shape} is different from that of inplace tensor {var.shape} in the Inplace operation."
)
return paddle.bitwise_xor_(var, self.y)

def non_inplace_api_processing(self, var):
return paddle.bitwise_xor(input=var, other=self.y)


class TestDygraphInplacBitwiseXorAlias3(TestDygraphInplacBitwiseAnd):
def inplace_api_processing(self, var):
out_shape = paddle.broadcast_shape(var.shape, self.y.shape)
if var.shape != out_shape:
raise ValueError(
f"The shape of broadcast output {out_shape} is different from that of inplace tensor {var.shape} in the Inplace operation."
)
return paddle.bitwise_xor_(var, self.y)

def non_inplace_api_processing(self, var):
return paddle.bitwise_xor(x=var, y=self.y)


class TestDygraphInplacBitwiseXorAlias4(TestDygraphInplacBitwiseAnd):
def inplace_api_processing(self, var):
out_shape = paddle.broadcast_shape(var.shape, self.y.shape)
if var.shape != out_shape:
raise ValueError(
f"The shape of broadcast output {out_shape} is different from that of inplace tensor {var.shape} in the Inplace operation."
)
return paddle.bitwise_xor_(var, self.y)

def non_inplace_api_processing(self, var):
return paddle.bitwise_xor(x=var, other=self.y)


class TestDygraphInplacBitwiseNot(TestDygraphInplacBitwiseAnd):
def inplace_api_processing(self, var):
return paddle.bitwise_not_(var)
Expand Down
6 changes: 3 additions & 3 deletions test/legacy_test/test_zero_dim_binary_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def test_dygraph_binary(self):
# 1) x is 0D, y is 0D
x_np = np.random.randint(-10, 10, [])
y_np = np.random.randint(-10, 10, [])
out_np = eval(f'np.{api.__name__}(x_np, y_np)')
out_np = eval(f'np.{api.__name__.lstrip("_")}(x_np, y_np)')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zero_dim这里为啥需要改

Copy link
Contributor Author

@Manfredss Manfredss Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的改动是因为测试会有报错

======================================================================
ERROR: test_dygraph_binary (__main__.TestBinaryAPI.test_dygraph_binary)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:\Xue\ML\PaddleDebug\test\legacy_test\test_zero_dim_binary_api.py", line 170, in test_dygraph_binary
    out_np = eval(f'np.{api.__name__}(x_np, y_np)')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
  File "C:\Users\tzy12\anaconda3\envs\paddle\Lib\site-packages\numpy\__init__.py", line 808, in __getattr__
    raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
AttributeError: module 'numpy' has no attribute '_bitwise_xor'. Did you mean: 'bitwise_xor'?

----------------------------------------------------------------------
Ran 6 tests in 0.508s


x = paddle.to_tensor(x_np)
y = paddle.to_tensor(y_np)
Expand All @@ -179,7 +179,7 @@ def test_dygraph_binary(self):
# 2) x is ND, y is 0D
x_np = np.random.randint(-10, 10, [3, 5])
y_np = np.random.randint(-10, 10, [])
out_np = eval(f'np.{api.__name__}(x_np, y_np)')
out_np = eval(f'np.{api.__name__.lstrip("_")}(x_np, y_np)')

x = paddle.to_tensor(x_np)
y = paddle.to_tensor(y_np)
Expand All @@ -191,7 +191,7 @@ def test_dygraph_binary(self):
# 3) x is 0D , y is ND
x_np = np.random.randint(-10, 10, [])
y_np = np.random.randint(-10, 10, [3, 5])
out_np = eval(f'np.{api.__name__}(x_np, y_np)')
out_np = eval(f'np.{api.__name__.lstrip("_")}(x_np, y_np)')

x = paddle.to_tensor(x_np)
y = paddle.to_tensor(y_np)
Expand Down
6 changes: 3 additions & 3 deletions test/xpu/test_zero_dim_tensor_xpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def test_dygraph_binary(self):
# 1) x is 0D, y is 0D
x_np = np.random.randint(-10, 10, [])
y_np = np.random.randint(-10, 10, [])
out_np = eval(f'np.{api.__name__}(x_np, y_np)')
out_np = eval(f'np.{api.__name__.lstrip("_")}(x_np, y_np)')

x = paddle.to_tensor(x_np)
y = paddle.to_tensor(y_np)
Expand All @@ -357,7 +357,7 @@ def test_dygraph_binary(self):
# 2) x is ND, y is 0D
x_np = np.random.randint(-10, 10, [3, 5])
y_np = np.random.randint(-10, 10, [])
out_np = eval(f'np.{api.__name__}(x_np, y_np)')
out_np = eval(f'np.{api.__name__.lstrip("_")}(x_np, y_np)')

x = paddle.to_tensor(x_np)
y = paddle.to_tensor(y_np)
Expand All @@ -369,7 +369,7 @@ def test_dygraph_binary(self):
# 3) x is 0D , y is ND
x_np = np.random.randint(-10, 10, [])
y_np = np.random.randint(-10, 10, [3, 5])
out_np = eval(f'np.{api.__name__}(x_np, y_np)')
out_np = eval(f'np.{api.__name__.lstrip("_")}(x_np, y_np)')

x = paddle.to_tensor(x_np)
y = paddle.to_tensor(y_np)
Expand Down
Loading