Skip to content

Commit

Permalink
【PaddlePaddle Hackathon 3 No.14】为 Paddle 新增 remainder_ API (#45266)
Browse files Browse the repository at this point in the history
  • Loading branch information
zrr1999 committed Aug 31, 2022
1 parent 236ac0d commit fe2bfe1
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 3 deletions.
3 changes: 2 additions & 1 deletion paddle/fluid/operators/elementwise/elementwise_mod_op.cc
Expand Up @@ -56,7 +56,8 @@ class ElementwiseModOpMaker : public ElementwiseOpMaker {
namespace ops = paddle::operators;
REGISTER_OP_WITHOUT_GRADIENT(elementwise_mod,
ops::ElementwiseOp,
ops::ElementwiseModOpMaker);
ops::ElementwiseModOpMaker,
ops::ElementwiseOpInplaceInferer);

REGISTER_OP_VERSION(elementwise_mod)
.AddCheckpoint(
Expand Down
1 change: 1 addition & 0 deletions python/paddle/__init__.py
Expand Up @@ -239,6 +239,7 @@
from .tensor.math import divide # noqa: F401
from .tensor.math import floor_divide # noqa: F401
from .tensor.math import remainder # noqa: F401
from .tensor.math import remainder_ # noqa: F401
from .tensor.math import mod # noqa: F401
from .tensor.math import floor_mod # noqa: F401
from .tensor.math import multiply # noqa: F401
Expand Down
46 changes: 44 additions & 2 deletions python/paddle/fluid/tests/unittests/test_elementwise_mod_op.py
Expand Up @@ -97,12 +97,15 @@ def init_dtype(self):

class TestRemainderOp(unittest.TestCase):

def _executed_api(self, x, y, name=None):
return paddle.remainder(x, y, name)

def test_name(self):
with fluid.program_guard(fluid.Program()):
x = fluid.data(name="x", shape=[2, 3], dtype="int64")
y = fluid.data(name='y', shape=[2, 3], dtype='int64')

y_1 = paddle.remainder(x, y, name='div_res')
y_1 = self._executed_api(x, y, name='div_res')
self.assertEqual(('div_res' in y_1.name), True)

def test_dygraph(self):
Expand All @@ -111,7 +114,7 @@ def test_dygraph(self):
np_y = np.array([1, 5, 3, 3]).astype('int64')
x = paddle.to_tensor(np_x)
y = paddle.to_tensor(np_y)
z = paddle.remainder(x, y)
z = self._executed_api(x, y)
np_z = z.numpy()
z_expected = np.array([0, 3, 2, 1])
self.assertEqual((np_z == z_expected).all(), True)
Expand All @@ -133,5 +136,44 @@ def test_dygraph(self):
np.testing.assert_allclose(z_expected, z.numpy(), rtol=1e-05)


class TestRemainderInplaceOp(TestRemainderOp):

def _executed_api(self, x, y, name=None):
return x.remainder_(y, name)


class TestRemainderInplaceBroadcastSuccess(unittest.TestCase):

def init_data(self):
self.x_numpy = np.random.rand(2, 3, 4).astype('float')
self.y_numpy = np.random.rand(3, 4).astype('float')

def test_broadcast_success(self):
paddle.disable_static()
self.init_data()
x = paddle.to_tensor(self.x_numpy)
y = paddle.to_tensor(self.y_numpy)
inplace_result = x.remainder_(y)
numpy_result = self.x_numpy % self.y_numpy
self.assertEqual((inplace_result.numpy() == numpy_result).all(), True)
paddle.enable_static()


class TestRemainderInplaceBroadcastSuccess2(TestRemainderInplaceBroadcastSuccess
):

def init_data(self):
self.x_numpy = np.random.rand(1, 2, 3, 1).astype('float')
self.y_numpy = np.random.rand(3, 1).astype('float')


class TestRemainderInplaceBroadcastSuccess3(TestRemainderInplaceBroadcastSuccess
):

def init_data(self):
self.x_numpy = np.random.rand(2, 3, 1, 5).astype('float')
self.y_numpy = np.random.rand(1, 3, 1, 5).astype('float')


if __name__ == '__main__':
unittest.main()
23 changes: 23 additions & 0 deletions python/paddle/fluid/tests/unittests/test_inplace.py
Expand Up @@ -494,6 +494,29 @@ def inplace_api_processing(self, var):
return var.subtract_(input_var_2)


class TestDygraphInplaceRemainder(TestDygraphInplaceAdd):

def non_inplace_api_processing(self, var):
input_var_2 = paddle.to_tensor(self.input_var_numpy_2)
return var.remainder(input_var_2)

def inplace_api_processing(self, var):
input_var_2 = paddle.to_tensor(self.input_var_numpy_2)
return var.remainder_(input_var_2)

def test_leaf_inplace_var_error(self):
pass

def test_backward_error(self):
pass

def test_backward_success_1(self):
pass

def test_backward_success_2(self):
pass


class TestLossIsInplaceVar(unittest.TestCase):

def func_test_loss_is_inplace_var(self):
Expand Down
2 changes: 2 additions & 0 deletions python/paddle/tensor/__init__.py
Expand Up @@ -184,6 +184,7 @@
from .math import divide # noqa: F401
from .math import floor_divide # noqa: F401
from .math import remainder # noqa: F401
from .math import remainder_ # noqa: F401
from .math import mod # noqa: F401
from .math import floor_mod # noqa: F401
from .math import multiply # noqa: F401
Expand Down Expand Up @@ -367,6 +368,7 @@
'divide',
'floor_divide',
'remainder',
'remainder_',
'mod',
'floor_mod',
'multiply',
Expand Down
18 changes: 18 additions & 0 deletions python/paddle/tensor/math.py
Expand Up @@ -784,6 +784,24 @@ def remainder(x, y, name=None):
return _elementwise_op(LayerHelper(op_type, **locals()))


@inplace_apis_in_dygraph_only
def remainder_(x, y, name=None):
r"""
Inplace version of ``remainder`` API, the output Tensor will be inplaced with input ``x``.
Please refer to :ref:`api_tensor_remainder`.
"""
op_type = 'elementwise_mod_'
axis = -1

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

return _elementwise_op_in_dygraph(x, y, axis=axis, op_name=op_type)


mod = remainder # noqa: F841
floor_mod = remainder # noqa: F841

Expand Down

0 comments on commit fe2bfe1

Please sign in to comment.