From 2e4b22cb2db8a457aa4a29d092fdbff6c67c80eb Mon Sep 17 00:00:00 2001 From: Ke Han Date: Tue, 11 Feb 2020 17:26:06 +0000 Subject: [PATCH 1/7] [Numpy] Add op fmax, fmin * Fix sanity * Fix bug of gpu part, add scalar compute * Finish cpu,gpu test of fmax, fmin --- 3rdparty/dlpack | 2 +- python/mxnet/ndarray/numpy/_op.py | 40 ++++++++++- python/mxnet/numpy/multiarray.py | 61 ++++++++++++++++- python/mxnet/numpy_dispatch_protocol.py | 2 + python/mxnet/symbol/numpy/_symbol.py | 15 ++++- src/operator/mshadow_op.h | 28 ++++++++ .../np_elemwise_broadcast_op_extended.cc | 66 +++++++++++++++++++ .../np_elemwise_broadcast_op_extended.cu | 26 ++++++++ src/operator/operator_tune.cc | 2 + .../unittest/test_numpy_interoperability.py | 16 +++++ tests/python/unittest/test_numpy_op.py | 4 ++ 11 files changed, 258 insertions(+), 4 deletions(-) diff --git a/3rdparty/dlpack b/3rdparty/dlpack index 3efc489b5538..b90e93907206 160000 --- a/3rdparty/dlpack +++ b/3rdparty/dlpack @@ -1 +1 @@ -Subproject commit 3efc489b55385936531a06ff83425b719387ec63 +Subproject commit b90e939072066c160b18ea1e7156537b8d3710f6 diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index e235c54b8711..b19a6ea37c2b 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -38,7 +38,7 @@ 'tensordot', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'array_split', 'split', 'hsplit', 'vsplit', 'dsplit', 'concatenate', 'append', 'stack', 'vstack', 'row_stack', 'column_stack', 'hstack', 'dstack', - 'average', 'mean', 'maximum', 'minimum', 'around', 'round', 'round_', 'flatnonzero', + 'average', 'mean', 'maximum', 'fmax', 'minimum', 'fmin', 'around', 'round', 'round_', 'flatnonzero', 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'unravel_index', 'diag_indices_from', 'hanning', 'hamming', 'blackman', 'flip', 'flipud', 'fliplr', 'hypot', 'bitwise_and', 'bitwise_xor', 'bitwise_or', 'rad2deg', 'deg2rad', 'unique', 'lcm', @@ -4366,6 +4366,25 @@ def maximum(x1, x2, out=None, **kwargs): return _ufunc_helper(x1, x2, _npi.maximum, _np.maximum, _npi.maximum_scalar, None, out) +@set_module('mxnet.ndarray.numpy') +@wrap_np_binary_func +def fmax(x1, x2, out=None, **kwargs): + """ + Returns element-wise maximum of the input arrays with broadcasting. (Ignores NaNs) + + Parameters + ---------- + x1, x2 : scalar or mxnet.numpy.ndarray + The arrays holding the elements to be compared. They must have the same shape, + or shapes that can be broadcast to a single shape. + + Returns + ------- + out : mxnet.numpy.ndarray or scalar + The maximum of x1 and x2, element-wise. This is a scalar if both x1 and x2 are scalars.""" + return _ufunc_helper(x1, x2, _npi.fmax, _np.fmax, _npi.fmax_scalar, None, out) + + @set_module('mxnet.ndarray.numpy') @wrap_np_binary_func def minimum(x1, x2, out=None, **kwargs): @@ -4385,6 +4404,25 @@ def minimum(x1, x2, out=None, **kwargs): return _ufunc_helper(x1, x2, _npi.minimum, _np.minimum, _npi.minimum_scalar, None, out) +@set_module('mxnet.ndarray.numpy') +@wrap_np_binary_func +def fmin(x1, x2, out=None, **kwargs): + """ + Returns element-wise minimum of the input arrays with broadcasting. (Ignores NaNs) + + Parameters + ---------- + x1, x2 : scalar or mxnet.numpy.ndarray + The arrays holding the elements to be compared. They must have the same shape, + or shapes that can be broadcast to a single shape. + + Returns + ------- + out : mxnet.numpy.ndarray or scalar + The minimum of x1 and x2, element-wise. This is a scalar if both x1 and x2 are scalars.""" + return _ufunc_helper(x1, x2, _npi.fmin, _np.fmin, _npi.fmin_scalar, None, out) + + @set_module('mxnet.ndarray.numpy') def swapaxes(a, axis1, axis2): """Interchange two axes of an array. diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py index 09712c03ea96..8724f8850b33 100644 --- a/python/mxnet/numpy/multiarray.py +++ b/python/mxnet/numpy/multiarray.py @@ -61,7 +61,8 @@ 'sort', 'tensordot', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'array_split', 'split', 'hsplit', 'vsplit', 'dsplit', 'flatnonzero', 'concatenate', 'stack', 'vstack', 'row_stack', 'column_stack', 'hstack', 'dstack', - 'average', 'mean', 'maximum', 'minimum', 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'insert', + 'average', 'mean', 'maximum', 'fmax', 'minimum', 'fmin', + 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'insert', 'indices', 'copysign', 'ravel', 'unravel_index', 'diag_indices_from', 'hanning', 'hamming', 'blackman', 'flip', 'flipud', 'fliplr', 'around', 'round', 'round_', 'arctan2', 'hypot', 'bitwise_and', 'bitwise_xor', 'bitwise_or', 'rad2deg', 'deg2rad', @@ -6185,6 +6186,35 @@ def maximum(x1, x2, out=None, **kwargs): return _mx_nd_np.maximum(x1, x2, out=out) +@set_module('mxnet.numpy') +@wrap_np_binary_func +def fmax(x1, x2, out=None, **kwargs): + """ + Returns element-wise maximum of the input arrays with broadcasting. (Ignores NaNs) + + Parameters + ---------- + x1, x2 : scalar or mxnet.numpy.ndarray + The arrays holding the elements to be compared. They must have the same shape, + or shapes that can be broadcast to a single shape. + + Returns + ------- + out : mxnet.numpy.ndarray or scalar + The maximum of x1 and x2, element-wise. This is a scalar if both x1 and x2 are scalars. + + Examples + -------- + >>> np.fmax(np.array([2, 3, 4]), np.array([1, 5, 2])) + array([2., 5., 4.]) + + >>> np.fmax(np.eye(2), np.array([0.5, 2])) # broadcasting + array([[1. , 2. ], + [0.5, 2. ]]) + """ + return _mx_nd_np.fmax(x1, x2, out=out) + + @set_module('mxnet.numpy') @wrap_np_binary_func def minimum(x1, x2, out=None, **kwargs): @@ -6214,6 +6244,35 @@ def minimum(x1, x2, out=None, **kwargs): return _mx_nd_np.minimum(x1, x2, out=out) +@set_module('mxnet.numpy') +@wrap_np_binary_func +def fmin(x1, x2, out=None, **kwargs): + """ + Returns element-wise minimum of the input arrays with broadcasting. (Ignores NaNs) + + Parameters + ---------- + x1, x2 : scalar or mxnet.numpy.ndarray + The arrays holding the elements to be compared. They must have the same shape, + or shapes that can be broadcast to a single shape. + + Returns + ------- + out : mxnet.numpy.ndarray or scalar + The fmin of x1 and x2, element-wise. This is a scalar if both x1 and x2 are scalars. + + Examples + -------- + >>> np.fmin(np.array([2, 3, 4]), np.array([1, 5, 2])) + array([1., 3., 2.]) + + >>> np.fmin(np.eye(2), np.array([0.5, 2])) # broadcasting + array([[0.5, 0. ], + [0. , 1. ]]) + """ + return _mx_nd_np.fmin(x1, x2, out=out) + + @set_module('mxnet.numpy') def swapaxes(a, axis1, axis2): """Interchange two axes of an array. diff --git a/python/mxnet/numpy_dispatch_protocol.py b/python/mxnet/numpy_dispatch_protocol.py index 781ec55b3796..ada60b389ff8 100644 --- a/python/mxnet/numpy_dispatch_protocol.py +++ b/python/mxnet/numpy_dispatch_protocol.py @@ -277,7 +277,9 @@ def _register_array_function(): 'arccosh', 'arctanh', 'maximum', + 'fmax', 'minimum', + 'fmin', 'ceil', 'trunc', 'floor', diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py index 11e574ae5fd9..57b20f361032 100644 --- a/python/mxnet/symbol/numpy/_symbol.py +++ b/python/mxnet/symbol/numpy/_symbol.py @@ -43,7 +43,8 @@ 'trunc', 'logical_not', 'arcsinh', 'arccosh', 'arctanh', 'argsort', 'sort', 'tensordot', 'eye', 'linspace', 'logspace', 'expand_dims', 'tile', 'arange', 'array_split', 'split', 'hsplit', 'vsplit', 'dsplit', 'concatenate', 'append', 'stack', 'vstack', 'row_stack', 'column_stack', 'hstack', 'dstack', - 'average', 'mean', 'maximum', 'minimum', 'any', 'all', 'around', 'round', 'round_', 'flatnonzero', + 'average', 'mean', 'maximum', 'fmax', 'minimum', 'fmin', 'any', 'all', 'around', 'round', 'round_', + 'flatnonzero', 'swapaxes', 'clip', 'argmax', 'argmin', 'std', 'var', 'indices', 'copysign', 'ravel', 'unravel_index', 'diag_indices_from', 'hanning', 'hamming', 'blackman', 'flip', 'flipud', 'fliplr', 'hypot', 'bitwise_and', 'bitwise_xor', 'bitwise_or', 'rad2deg', 'deg2rad', 'unique', 'lcm', @@ -4127,6 +4128,12 @@ def maximum(x1, x2, out=None, **kwargs): return _ufunc_helper(x1, x2, _npi.maximum, _np.maximum, _npi.maximum_scalar, None, out) +@set_module('mxnet.symbol.numpy') +@wrap_np_binary_func +def fmax(x1, x2, out=None, **kwargs): + return _ufunc_helper(x1, x2, _npi.fmax, _np.fmax, _npi.fmax_scalar, None, out) + + @set_module('mxnet.symbol.numpy') @wrap_np_binary_func def minimum(x1, x2, out=None, **kwargs): @@ -4134,6 +4141,7 @@ def minimum(x1, x2, out=None, **kwargs): @set_module('mxnet.symbol.numpy') +<<<<<<< HEAD def all(a, axis=None, out=None, keepdims=False): """ Test whether all array elements along a given axis evaluate to True. @@ -4192,6 +4200,11 @@ def any(a, axis=None, out=None, keepdims=False): in which case a reference to out is returned. """ return _npi.any(a, axis=axis, keepdims=keepdims, out=out) +======= +@wrap_np_binary_func +def fmin(x1, x2, out=None, **kwargs): + return _ufunc_helper(x1, x2, _npi.fmin, _np.fmin, _npi.fmin_scalar, None, out) +>>>>>>> [Numpy] Add op fmax, fmin @set_module('mxnet.symbol.numpy') diff --git a/src/operator/mshadow_op.h b/src/operator/mshadow_op.h index 9106ee222542..2ced8110316d 100644 --- a/src/operator/mshadow_op.h +++ b/src/operator/mshadow_op.h @@ -1143,6 +1143,20 @@ struct maximum : public mxnet_op::tunable { } }; +/*! \brief used for computing binary operator fmax */ +struct fmax : public mxnet_op::tunable { + template + MSHADOW_XINLINE static DType Map(DType a, DType b) { + if (IsNan(b)) { + return a; + } else if (IsNan(a)) { + return b; + } else { + return (a > b ? a : b); + } + } +}; + /*! \brief used for computing binary operator minimum */ struct minimum : public mxnet_op::tunable { template @@ -1155,6 +1169,20 @@ struct minimum : public mxnet_op::tunable { } }; +/*! \brief used for computing binary operator fmin */ +struct fmin : public mxnet_op::tunable { + template + MSHADOW_XINLINE static DType Map(DType a, DType b) { + if (IsNan(b)) { + return a; + } else if (IsNan(a)) { + return b; + } else { + return (a < b ? a : b); + } + } +}; + /*! \brief boolean any/all kernel that determines whether elem is NonZero */ struct NonZero { template diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc index 70233a596dc7..5a69cd51bcd4 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -371,5 +371,71 @@ MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_rldexp_scalar) .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(broadcast_fmax) +.add_alias("_npi_fmax") +.set_attr("FCompute", BinaryBroadcastCompute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_broadcast_fmax"}); + +NNVM_REGISTER_OP(_backward_broadcast_fmax) +.add_alias("_backward_npi_fmax") +.set_num_inputs(3) +.set_num_outputs(2) +.set_attr("TIsBackward", true) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 1}}; + }) +.set_attr("FResourceRequest", + [](const NodeAttrs& attrs) { + return std::vector{ResourceRequest::kTempSpace}; + }) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_fmax_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_fmax_scalar"}) +.add_alias("_FmaxScalar") +.add_alias("_npi_fmax_scalar"); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_fmax_scalar) +.add_alias("_backward_npi_fmax_scalar") +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(broadcast_fmin) +.add_alias("_npi_fmin") +.set_attr("FCompute", BinaryBroadcastCompute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_broadcast_fmin"}); + +NNVM_REGISTER_OP(_backward_broadcast_fmin) +.add_alias("_backward_npi_fmin") +.set_num_inputs(3) +.set_num_outputs(2) +.set_attr("TIsBackward", true) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 1}}; + }) +.set_attr("FResourceRequest", + [](const NodeAttrs& attrs) { + return std::vector{ResourceRequest::kTempSpace}; + }) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_fmin_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_fmin_scalar"}) +.add_alias("_FminScalar") +.add_alias("_npi_fmin_scalar"); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_fmin_scalar) +.add_alias("_backward_npi_fmin_scalar") +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + } // namespace op } // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu index 8f135b3efd03..c62a663a4f17 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu @@ -116,5 +116,31 @@ NNVM_REGISTER_OP(_backward_npi_ldexp_scalar) NNVM_REGISTER_OP(_backward_npi_rldexp_scalar) .set_attr("FCompute", BinaryScalarOp::Backward); +NNVM_REGISTER_OP(_npi_fmax) +.set_attr("FCompute", BinaryBroadcastCompute); + +NNVM_REGISTER_OP(_backward_npi_fmax) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +NNVM_REGISTER_OP(_npi_fmax_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_fmax_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + +NNVM_REGISTER_OP(_npi_fmin) +.set_attr("FCompute", BinaryBroadcastCompute); + +NNVM_REGISTER_OP(_backward_npi_fmin) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +NNVM_REGISTER_OP(_npi_fmin_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_fmin_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + } // namespace op } // namespace mxnet diff --git a/src/operator/operator_tune.cc b/src/operator/operator_tune.cc index 0cc0dc92f884..7e39671af4b6 100644 --- a/src/operator/operator_tune.cc +++ b/src/operator/operator_tune.cc @@ -375,7 +375,9 @@ IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::gelu_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::prelu_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::elu_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::maximum); // NOLINT() +IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::fmax); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::minimum); // NOLINT() +IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::fmin); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::hypot); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::hypot_grad_left); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::hypot_grad_left); // NOLINT() diff --git a/tests/python/unittest/test_numpy_interoperability.py b/tests/python/unittest/test_numpy_interoperability.py index 2d1710eeedc9..9f6e8d632b13 100644 --- a/tests/python/unittest/test_numpy_interoperability.py +++ b/tests/python/unittest/test_numpy_interoperability.py @@ -1481,6 +1481,13 @@ def _add_workload_maximum(array_pool): OpArgMngr.add_workload('maximum', array_pool['4x1'], array_pool['1x1x0']) +def _add_workload_fmax(array_pool): + OpArgMngr.add_workload('fmax', array_pool['4x1'], array_pool['1x2']) + OpArgMngr.add_workload('fmax', array_pool['4x1'], 2) + OpArgMngr.add_workload('fmax', 2, array_pool['4x1']) + OpArgMngr.add_workload('fmax', array_pool['4x1'], array_pool['1x1x0']) + + def _add_workload_minimum(array_pool): OpArgMngr.add_workload('minimum', array_pool['4x1'], array_pool['1x2']) OpArgMngr.add_workload('minimum', array_pool['4x1'], 2) @@ -1488,6 +1495,13 @@ def _add_workload_minimum(array_pool): OpArgMngr.add_workload('minimum', array_pool['4x1'], array_pool['1x1x0']) +def _add_workload_fmin(array_pool): + OpArgMngr.add_workload('fmin', array_pool['4x1'], array_pool['1x2']) + OpArgMngr.add_workload('fmin', array_pool['4x1'], 2) + OpArgMngr.add_workload('fmin', 2, array_pool['4x1']) + OpArgMngr.add_workload('fmin', array_pool['4x1'], array_pool['1x1x0']) + + def _add_workload_negative(array_pool): OpArgMngr.add_workload('negative', array_pool['4x1']) @@ -2835,7 +2849,9 @@ def _prepare_workloads(): _add_workload_mod(array_pool) _add_workload_remainder() _add_workload_maximum(array_pool) + _add_workload_fmax(array_pool) _add_workload_minimum(array_pool) + _add_workload_fmin(array_pool) _add_workload_negative(array_pool) _add_workload_absolute(array_pool) _add_workload_sign(array_pool) diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py index 85dbe70397d5..467691560754 100644 --- a/tests/python/unittest/test_numpy_op.py +++ b/tests/python/unittest/test_numpy_op.py @@ -2268,8 +2268,12 @@ def hybrid_forward(self, F, a, b, *args, **kwargs): 'bitwise_or': (-100, 100, [None], None, [[_np.int32]]), 'maximum': (-1, 1, [lambda y, x1, x2: _np.ones(y.shape) * (x1 >= x2)], [lambda y, x1, x2: _np.ones(y.shape) * (x1 < x2)]), + 'fmax': (-1, 1, [lambda y, x1, x2: _np.ones(y.shape) * (x1 >= x2)], + [lambda y, x1, x2: _np.ones(y.shape) * (x1 < x2)]), 'minimum': (-1, 1, [lambda y, x1, x2: _np.ones(y.shape) * (x1 <= x2)], [lambda y, x1, x2: _np.ones(y.shape) * (x1 > x2)]), + 'fmin': (-1, 1, [lambda y, x1, x2: _np.ones(y.shape) * (x1 <= x2)], + [lambda y, x1, x2: _np.ones(y.shape) * (x1 > x2)]), 'copysign': (-1, 1, [lambda y, x1, x2: _np.ones(y.shape) * (((x1 * x2) >= 0).astype(_np.float32) - ((x1 * x2) < 0).astype(_np.float32))], [lambda y, x1, x2: _np.zeros(y.shape)]), From ef3bd4d0120bc9d899971c885976de9c36413108 Mon Sep 17 00:00:00 2001 From: Ke Han Date: Tue, 18 Feb 2020 16:05:25 +0000 Subject: [PATCH 2/7] * Fix 3rd Party --- 3rdparty/dlpack | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/dlpack b/3rdparty/dlpack index b90e93907206..3efc489b5538 160000 --- a/3rdparty/dlpack +++ b/3rdparty/dlpack @@ -1 +1 @@ -Subproject commit b90e939072066c160b18ea1e7156537b8d3710f6 +Subproject commit 3efc489b55385936531a06ff83425b719387ec63 From 3b1e4dc886c6359744453e4ba70222b9740f1c4b Mon Sep 17 00:00:00 2001 From: Han Date: Sun, 23 Feb 2020 16:14:05 +0800 Subject: [PATCH 3/7] * Prune redundent alias --- .../np_elemwise_broadcast_op_extended.cc | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc index 5a69cd51bcd4..9bc550e94b94 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -371,13 +371,11 @@ MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_rldexp_scalar) .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); -MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(broadcast_fmax) -.add_alias("_npi_fmax") +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmax) .set_attr("FCompute", BinaryBroadcastCompute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_broadcast_fmax"}); +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmax"}); -NNVM_REGISTER_OP(_backward_broadcast_fmax) -.add_alias("_backward_npi_fmax") +NNVM_REGISTER_OP(_backward_npi_fmax) .set_num_inputs(3) .set_num_outputs(2) .set_attr("TIsBackward", true) @@ -392,25 +390,20 @@ NNVM_REGISTER_OP(_backward_broadcast_fmax) .set_attr("FCompute", BinaryBroadcastBackwardUseIn); -MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_fmax_scalar) +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmax_scalar) .set_attr("FCompute", BinaryScalarOp::Compute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_fmax_scalar"}) -.add_alias("_FmaxScalar") -.add_alias("_npi_fmax_scalar"); +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmax_scalar"}); -MXNET_OPERATOR_REGISTER_BINARY(_backward_fmax_scalar) -.add_alias("_backward_npi_fmax_scalar") +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmax_scalar) .add_argument("scalar", "float", "scalar value") .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); -MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(broadcast_fmin) -.add_alias("_npi_fmin") +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmin) .set_attr("FCompute", BinaryBroadcastCompute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_broadcast_fmin"}); +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmin"}); -NNVM_REGISTER_OP(_backward_broadcast_fmin) -.add_alias("_backward_npi_fmin") +NNVM_REGISTER_OP(_backward_npi_fmin) .set_num_inputs(3) .set_num_outputs(2) .set_attr("TIsBackward", true) @@ -425,14 +418,11 @@ NNVM_REGISTER_OP(_backward_broadcast_fmin) .set_attr("FCompute", BinaryBroadcastBackwardUseIn); -MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_fmin_scalar) +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmin_scalar) .set_attr("FCompute", BinaryScalarOp::Compute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_fmin_scalar"}) -.add_alias("_FminScalar") -.add_alias("_npi_fmin_scalar"); +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmin_scalar"}); -MXNET_OPERATOR_REGISTER_BINARY(_backward_fmin_scalar) -.add_alias("_backward_npi_fmin_scalar") +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmin_scalar) .add_argument("scalar", "float", "scalar value") .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); From e0b668f7b70c1fc63441aa1d7e077a7a6d284d4e Mon Sep 17 00:00:00 2001 From: Ke Han Date: Mon, 24 Feb 2020 01:55:45 +0800 Subject: [PATCH 4/7] * Add op fmod (rfmod still need check) --- python/mxnet/ndarray/numpy/_op.py | 30 +++++++++++++++- python/mxnet/numpy/multiarray.py | 35 ++++++++++++++++++- python/mxnet/numpy_dispatch_protocol.py | 1 + python/mxnet/symbol/numpy/_symbol.py | 9 ++++- src/operator/mshadow_op.h | 11 ++++++ .../np_elemwise_broadcast_op_extended.cc | 28 +++++++++++++++ .../np_elemwise_broadcast_op_extended.cu | 13 +++++++ src/operator/operator_tune.cc | 1 + .../unittest/test_numpy_interoperability.py | 8 +++++ tests/python/unittest/test_numpy_op.py | 6 ++++ 10 files changed, 139 insertions(+), 3 deletions(-) diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index b19a6ea37c2b..d7ae73e6f2c9 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -30,7 +30,8 @@ __all__ = ['shape', 'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 'empty_like', 'invert', 'delete', - 'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'power', 'bitwise_not', + 'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'fmod', + 'power', 'bitwise_not', 'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', 'abs', 'insert', 'fabs', 'absolute', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'matmul', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor', 'histogram', @@ -1169,6 +1170,33 @@ def mod(x1, x2, out=None, **kwargs): return _api_internal.mod(x1, x2, out) +@set_module('mxnet.ndarray.numpy') +@wrap_np_binary_func +def fmod(x1, x2, out=None, **kwargs): + """ + Return element-wise remainder of division. + + Parameters + ---------- + x1 : ndarray or scalar + Dividend array. + + x2 : ndarray or scalar + Divisor array. + + out : ndarray + A location into which the result is stored. If provided, it must have a shape + that the inputs broadcast to. If not provided or None, a freshly-allocated array + is returned. + + Returns + ------- + out : ndarray or scalar + This is a scalar if both x1 and x2 are scalars. + """ + return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, out) + + @set_module('mxnet.ndarray.numpy') def delete(arr, obj, axis=None): """ diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py index 8724f8850b33..6aa9c26e7020 100644 --- a/python/mxnet/numpy/multiarray.py +++ b/python/mxnet/numpy/multiarray.py @@ -53,7 +53,8 @@ __all__ = ['ndarray', 'empty', 'empty_like', 'array', 'shape', 'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 'all', 'any', 'broadcast_to', - 'add', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'power', 'bitwise_not', 'delete', + 'add', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'fmod', 'power', 'bitwise_not', + 'delete', 'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'invert', 'sqrt', 'cbrt', 'abs', 'absolute', 'fabs', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'log1p', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'histogram', @@ -3148,6 +3149,38 @@ def mod(x1, x2, out=None, **kwargs): return _mx_nd_np.mod(x1, x2, out=out) +@set_module('mxnet.numpy') +@wrap_np_binary_func +def fmod(x1, x2, out=None, **kwargs): + """ + Return element-wise remainder of division. + + Parameters + ---------- + x1 : ndarray or scalar + Dividend array. + + x2 : ndarray or scalar + Divisor array. + + out : ndarray + A location into which the result is stored. If provided, it must have a shape + that the inputs broadcast to. If not provided or None, a freshly-allocated array + is returned. + + Returns + ------- + out : ndarray or scalar + This is a scalar if both x1 and x2 are scalars. + + Examples + -------- + >>> np.fmod(np.arange(7), 5) + array([0., 1., 2., 3., 4., 0., 1.]) + """ + return _mx_nd_np.fmod(x1, x2, out=out) + + @set_module('mxnet.numpy') @wrap_np_binary_func def matmul(a, b, out=None, **kwargs): diff --git a/python/mxnet/numpy_dispatch_protocol.py b/python/mxnet/numpy_dispatch_protocol.py index ada60b389ff8..a4b251b55607 100644 --- a/python/mxnet/numpy_dispatch_protocol.py +++ b/python/mxnet/numpy_dispatch_protocol.py @@ -248,6 +248,7 @@ def _register_array_function(): 'negative', 'power', 'mod', + 'fmod', 'matmul', 'absolute', 'rint', diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py index 57b20f361032..fca784c10a4e 100644 --- a/python/mxnet/symbol/numpy/_symbol.py +++ b/python/mxnet/symbol/numpy/_symbol.py @@ -36,7 +36,8 @@ from builtins import slice as py_slice __all__ = ['zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like', 'empty_like', 'bitwise_not', 'invert', - 'delete', 'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'power', 'arctan2', + 'delete', 'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod', 'remainder', 'fmod', + 'power', 'arctan2', 'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt', 'cbrt', 'abs', 'absolute', 'fabs', 'exp', 'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees', 'log2', 'log1p', 'matmul', 'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix', 'ceil', 'floor', 'histogram', 'insert', @@ -1621,6 +1622,12 @@ def mod(x1, x2, out=None, **kwargs): return _ufunc_helper(x1, x2, _npi.mod, _np.mod, _npi.mod_scalar, _npi.rmod_scalar, out) +@set_module('mxnet.symbol.numpy') +@wrap_np_binary_func +def fmod(x1, x2, out=None, **kwargs): + return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, out) + + @set_module('mxnet.symbol.numpy') @wrap_np_binary_func def remainder(x1, x2, out=None, **kwargs): diff --git a/src/operator/mshadow_op.h b/src/operator/mshadow_op.h index 2ced8110316d..947770cb8f45 100644 --- a/src/operator/mshadow_op.h +++ b/src/operator/mshadow_op.h @@ -807,6 +807,17 @@ struct mod : public mxnet_op::tunable { } }; +struct fmod : public mxnet_op::tunable { + template + MSHADOW_XINLINE static DType Map(DType a, DType b) { + if (b == DType(0)) { + return DType(0); + } else { + return DType(::fmod(static_cast(a), static_cast(b))); + } + } +}; + template<> MSHADOW_XINLINE mshadow::half::half2_t mod::Map (mshadow::half::half2_t a, diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc index 9bc550e94b94..308e254c2b4d 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -427,5 +427,33 @@ MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmin_scalar) .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmod) +.set_attr("FCompute", BinaryBroadcastCompute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmod"}); + +NNVM_REGISTER_OP(_backward_npi_fmod) +.set_num_inputs(3) +.set_num_outputs(2) +.set_attr("TIsBackward", true) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 1}}; + }) +.set_attr("FResourceRequest", + [](const NodeAttrs& attrs) { + return std::vector{ResourceRequest::kTempSpace}; + }) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmod_scalar"}); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmod_scalar) +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + } // namespace op } // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu index c62a663a4f17..3bb6b2d0aee6 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu @@ -142,5 +142,18 @@ NNVM_REGISTER_OP(_npi_fmin_scalar) NNVM_REGISTER_OP(_backward_npi_fmin_scalar) .set_attr("FCompute", BinaryScalarOp::Backward); +NNVM_REGISTER_OP(_npi_fmod) +.set_attr("FCompute", BinaryBroadcastCompute); + +NNVM_REGISTER_OP(_backward_npi_fmod) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +NNVM_REGISTER_OP(_npi_fmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_fmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + } // namespace op } // namespace mxnet diff --git a/src/operator/operator_tune.cc b/src/operator/operator_tune.cc index 7e39671af4b6..85a14765680f 100644 --- a/src/operator/operator_tune.cc +++ b/src/operator/operator_tune.cc @@ -345,6 +345,7 @@ IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::div_rgrad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::div_rgrad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::rdiv_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::mod); // NOLINT() +IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::fmod); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::mod_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::mod_rgrad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::rmod); // NOLINT() diff --git a/tests/python/unittest/test_numpy_interoperability.py b/tests/python/unittest/test_numpy_interoperability.py index 9f6e8d632b13..f58002c8634b 100644 --- a/tests/python/unittest/test_numpy_interoperability.py +++ b/tests/python/unittest/test_numpy_interoperability.py @@ -1415,6 +1415,13 @@ def _add_workload_mod(array_pool): OpArgMngr.add_workload('mod', array_pool['4x1'], array_pool['1x1x0']) +def _add_workload_fmod(array_pool): + OpArgMngr.add_workload('fmod', array_pool['4x1'], array_pool['1x2']) + OpArgMngr.add_workload('fmod', array_pool['4x1'], 2) + OpArgMngr.add_workload('fmod', 2, array_pool['4x1']) + OpArgMngr.add_workload('fmod', array_pool['4x1'], array_pool['1x1x0']) + + def _add_workload_remainder(): # test remainder basic OpArgMngr.add_workload('remainder', np.array([0, 1, 2, 4, 2], dtype=np.float16), @@ -2847,6 +2854,7 @@ def _prepare_workloads(): _add_workload_multiply(array_pool) _add_workload_power(array_pool) _add_workload_mod(array_pool) + _add_workload_fmod(array_pool) _add_workload_remainder() _add_workload_maximum(array_pool) _add_workload_fmax(array_pool) diff --git a/tests/python/unittest/test_numpy_op.py b/tests/python/unittest/test_numpy_op.py index 467691560754..ef5de655cbca 100644 --- a/tests/python/unittest/test_numpy_op.py +++ b/tests/python/unittest/test_numpy_op.py @@ -2254,6 +2254,12 @@ def hybrid_forward(self, F, a, b, *args, **kwargs): [lambda y, x1, x2: -_np.floor(x1 / x2), lambda y, x1, x2: _np.zeros(y.shape)], [[_np.float16, _np.float32, _np.float64], [_np.int32]]), + 'fmod': (1.0, 10.0, + [lambda y, x1, x2: _np.ones(y.shape), + lambda y, x1, x2: _np.zeros(y.shape)], + [lambda y, x1, x2: -_np.floor(x1 / x2), + lambda y, x1, x2: _np.zeros(y.shape)], + [[_np.float16, _np.float32, _np.float64], [_np.int32]]), 'remainder': (1.0, 10.0, [lambda y, x1, x2: _np.ones(y.shape), lambda y, x1, x2: _np.zeros(y.shape)], From 5f6a4d7ab2fbf9f273699d7a842a25bee6effe25 Mon Sep 17 00:00:00 2001 From: Ke Han Date: Mon, 24 Feb 2020 13:49:35 +0800 Subject: [PATCH 5/7] * Fix rfmod function --- python/mxnet/ndarray/numpy/_op.py | 2 +- python/mxnet/symbol/numpy/_symbol.py | 2 +- src/operator/mshadow_op.h | 11 +++++++++++ .../numpy/np_elemwise_broadcast_op_extended.cc | 9 +++++++++ .../numpy/np_elemwise_broadcast_op_extended.cu | 6 ++++++ src/operator/operator_tune.cc | 1 + 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index d7ae73e6f2c9..3fcc29b8deca 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -1194,7 +1194,7 @@ def fmod(x1, x2, out=None, **kwargs): out : ndarray or scalar This is a scalar if both x1 and x2 are scalars. """ - return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, out) + return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, _npi.rfmod_scalar, out) @set_module('mxnet.ndarray.numpy') diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py index fca784c10a4e..f0266e1fe823 100644 --- a/python/mxnet/symbol/numpy/_symbol.py +++ b/python/mxnet/symbol/numpy/_symbol.py @@ -1625,7 +1625,7 @@ def mod(x1, x2, out=None, **kwargs): @set_module('mxnet.symbol.numpy') @wrap_np_binary_func def fmod(x1, x2, out=None, **kwargs): - return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, out) + return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, _npi.rfmod_scalar, out) @set_module('mxnet.symbol.numpy') diff --git a/src/operator/mshadow_op.h b/src/operator/mshadow_op.h index 947770cb8f45..9f732343d882 100644 --- a/src/operator/mshadow_op.h +++ b/src/operator/mshadow_op.h @@ -818,6 +818,17 @@ struct fmod : public mxnet_op::tunable { } }; +struct rfmod : public mxnet_op::tunable { + template + MSHADOW_XINLINE static DType Map(DType a, DType b) { + if (a == DType(0)) { + return DType(0); + } else { + return DType(::fmod(static_cast(b), static_cast(a))); + } + } +}; + template<> MSHADOW_XINLINE mshadow::half::half2_t mod::Map (mshadow::half::half2_t a, diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc index 308e254c2b4d..3d79e3a4105a 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -455,5 +455,14 @@ MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmod_scalar) .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_rfmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_rfmod_scalar"}); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_rfmod_scalar) +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + } // namespace op } // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu index 3bb6b2d0aee6..8e3ec3db8784 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu @@ -155,5 +155,11 @@ NNVM_REGISTER_OP(_npi_fmod_scalar) NNVM_REGISTER_OP(_backward_npi_fmod_scalar) .set_attr("FCompute", BinaryScalarOp::Backward); +NNVM_REGISTER_OP(_npi_rfmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_rfmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + } // namespace op } // namespace mxnet diff --git a/src/operator/operator_tune.cc b/src/operator/operator_tune.cc index 85a14765680f..b76e341b9fc6 100644 --- a/src/operator/operator_tune.cc +++ b/src/operator/operator_tune.cc @@ -346,6 +346,7 @@ IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::div_rgrad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::rdiv_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::mod); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::fmod); // NOLINT() +IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::rfmod); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::mod_grad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_BWD(mxnet::op::mshadow_op::mod_rgrad); // NOLINT() IMPLEMENT_BINARY_WORKLOAD_FWD(mxnet::op::mshadow_op::rmod); // NOLINT() From 281946dc8fc40c06d5cda557e64e293e256c7b62 Mon Sep 17 00:00:00 2001 From: Ke Han Date: Tue, 10 Mar 2020 12:20:53 +0800 Subject: [PATCH 6/7] * Impl FFI --- python/mxnet/ndarray/numpy/_op.py | 14 +++-- .../np_elemwise_broadcast_op_extended.cc | 56 +++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index 3fcc29b8deca..addd12a9f286 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -1194,8 +1194,9 @@ def fmod(x1, x2, out=None, **kwargs): out : ndarray or scalar This is a scalar if both x1 and x2 are scalars. """ - return _ufunc_helper(x1, x2, _npi.fmod, _np.fmod, _npi.fmod_scalar, _npi.rfmod_scalar, out) - + if isinstance(x1, numeric_types) and isinstance(x2, numeric_types): + _np.fmod(x1, x2, out=out) + return _api_internal.fmod(x1, x2, out) @set_module('mxnet.ndarray.numpy') def delete(arr, obj, axis=None): @@ -4410,8 +4411,9 @@ def fmax(x1, x2, out=None, **kwargs): ------- out : mxnet.numpy.ndarray or scalar The maximum of x1 and x2, element-wise. This is a scalar if both x1 and x2 are scalars.""" - return _ufunc_helper(x1, x2, _npi.fmax, _np.fmax, _npi.fmax_scalar, None, out) - + if isinstance(x1, numeric_types) and isinstance(x2, numeric_types): + _np.fmax(x1, x2, out=out) + return _api_internal.fmax(x1, x2, out) @set_module('mxnet.ndarray.numpy') @wrap_np_binary_func @@ -4448,7 +4450,9 @@ def fmin(x1, x2, out=None, **kwargs): ------- out : mxnet.numpy.ndarray or scalar The minimum of x1 and x2, element-wise. This is a scalar if both x1 and x2 are scalars.""" - return _ufunc_helper(x1, x2, _npi.fmin, _np.fmin, _npi.fmin_scalar, None, out) + if isinstance(x1, numeric_types) and isinstance(x2, numeric_types): + _np.fmin(x1, x2, out=out) + return _api_internal.fmin(x1, x2, out) @set_module('mxnet.ndarray.numpy') diff --git a/src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc new file mode 100644 index 000000000000..f68a2deeaeca --- /dev/null +++ b/src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * \file np_elemwise_broadcast_op_extended.cc + * \brief Implementation of the API of functions in src/operator/numpy/np_elemwise_broadcast_op_extended.cc + */ +#include +#include +#include "../utils.h" +#include "../ufunc_helper.h" + +namespace mxnet { + +MXNET_REGISTER_API("_npi.fmax") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + const nnvm::Op* op = Op::Get("_npi_fmax"); + const nnvm::Op* op_scalar = Op::Get("_npi_fmax_scalar"); + UFuncHelper(args, ret, op, op_scalar, nullptr); +}); + +MXNET_REGISTER_API("_npi.fmin") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + const nnvm::Op* op = Op::Get("_npi_fmin"); + const nnvm::Op* op_scalar = Op::Get("_npi_fmin_scalar"); + UFuncHelper(args, ret, op, op_scalar, nullptr); +}); + +MXNET_REGISTER_API("_npi.fmod") +.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) { + using namespace runtime; + const nnvm::Op* op = Op::Get("_npi_fmod"); + const nnvm::Op* op_scalar = Op::Get("_npi_fmod_scalar"); + const nnvm::Op* op_rscalar = Op::Get("_npi_rfmod_scalar"); + UFuncHelper(args, ret, op, op_scalar, op_rscalar); +}); + +} // namespace mxnet From de1015854c5192145dd6e7ff7d090c180f9faae3 Mon Sep 17 00:00:00 2001 From: Ke Han Date: Mon, 16 Mar 2020 11:34:04 +0800 Subject: [PATCH 7/7] * Fix windows oversize by adding files --- benchmark/python/ffi/benchmark_ffi.py | 3 + python/mxnet/ndarray/numpy/_op.py | 2 + python/mxnet/symbol/numpy/_symbol.py | 12 +- ... np_elemwise_broadcast_op_extended_sec.cc} | 4 +- .../np_elemwise_broadcast_op_extended.cc | 93 ------------ .../np_elemwise_broadcast_op_extended.cu | 45 ------ .../np_elemwise_broadcast_op_extended_sec.cc | 142 ++++++++++++++++++ .../np_elemwise_broadcast_op_extended_sec.cu | 77 ++++++++++ 8 files changed, 232 insertions(+), 146 deletions(-) rename src/api/operator/numpy/{np_elemwise_broadcast_op_extended.cc => np_elemwise_broadcast_op_extended_sec.cc} (95%) create mode 100644 src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc create mode 100644 src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cu diff --git a/benchmark/python/ffi/benchmark_ffi.py b/benchmark/python/ffi/benchmark_ffi.py index 2b9d8dfa58fe..7740f6857ba4 100644 --- a/benchmark/python/ffi/benchmark_ffi.py +++ b/benchmark/python/ffi/benchmark_ffi.py @@ -77,6 +77,9 @@ def prepare_workloads(): OpArgMngr.add_workload("ones_like", pool['2x2']) OpArgMngr.add_workload("random.uniform", low=0, high=1, size=1) OpArgMngr.add_workload("where", pool['2x3'], pool['2x3'], pool['2x1']) + OpArgMngr.add_workload("fmax", pool['2x2'], pool['2x2']) + OpArgMngr.add_workload("fmin", pool['2x2'], pool['2x2']) + OpArgMngr.add_workload("fmod", pool['2x2'], pool['2x2']) OpArgMngr.add_workload("may_share_memory", pool['2x3'][:0], pool['2x3'][:1]) diff --git a/python/mxnet/ndarray/numpy/_op.py b/python/mxnet/ndarray/numpy/_op.py index addd12a9f286..76e936c1f7c4 100644 --- a/python/mxnet/ndarray/numpy/_op.py +++ b/python/mxnet/ndarray/numpy/_op.py @@ -1198,6 +1198,7 @@ def fmod(x1, x2, out=None, **kwargs): _np.fmod(x1, x2, out=out) return _api_internal.fmod(x1, x2, out) + @set_module('mxnet.ndarray.numpy') def delete(arr, obj, axis=None): """ @@ -4415,6 +4416,7 @@ def fmax(x1, x2, out=None, **kwargs): _np.fmax(x1, x2, out=out) return _api_internal.fmax(x1, x2, out) + @set_module('mxnet.ndarray.numpy') @wrap_np_binary_func def minimum(x1, x2, out=None, **kwargs): diff --git a/python/mxnet/symbol/numpy/_symbol.py b/python/mxnet/symbol/numpy/_symbol.py index f0266e1fe823..751c1355041a 100644 --- a/python/mxnet/symbol/numpy/_symbol.py +++ b/python/mxnet/symbol/numpy/_symbol.py @@ -4148,7 +4148,12 @@ def minimum(x1, x2, out=None, **kwargs): @set_module('mxnet.symbol.numpy') -<<<<<<< HEAD +@wrap_np_binary_func +def fmin(x1, x2, out=None, **kwargs): + return _ufunc_helper(x1, x2, _npi.fmin, _np.fmin, _npi.fmin_scalar, None, out) + + +@set_module('mxnet.symbol.numpy') def all(a, axis=None, out=None, keepdims=False): """ Test whether all array elements along a given axis evaluate to True. @@ -4207,11 +4212,6 @@ def any(a, axis=None, out=None, keepdims=False): in which case a reference to out is returned. """ return _npi.any(a, axis=axis, keepdims=keepdims, out=out) -======= -@wrap_np_binary_func -def fmin(x1, x2, out=None, **kwargs): - return _ufunc_helper(x1, x2, _npi.fmin, _np.fmin, _npi.fmin_scalar, None, out) ->>>>>>> [Numpy] Add op fmax, fmin @set_module('mxnet.symbol.numpy') diff --git a/src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/api/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc similarity index 95% rename from src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc rename to src/api/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc index f68a2deeaeca..248af4dd6e3e 100644 --- a/src/api/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/api/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc @@ -18,8 +18,8 @@ */ /*! - * \file np_elemwise_broadcast_op_extended.cc - * \brief Implementation of the API of functions in src/operator/numpy/np_elemwise_broadcast_op_extended.cc + * \file np_elemwise_broadcast_op_extended_sec.cc + * \brief Implementation of the API of functions in src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc */ #include #include diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc index 3d79e3a4105a..70233a596dc7 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cc +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cc @@ -371,98 +371,5 @@ MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_rldexp_scalar) .set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) .set_attr("FCompute", BinaryScalarOp::Backward); -MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmax) -.set_attr("FCompute", BinaryBroadcastCompute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmax"}); - -NNVM_REGISTER_OP(_backward_npi_fmax) -.set_num_inputs(3) -.set_num_outputs(2) -.set_attr("TIsBackward", true) -.set_attr("FInplaceOption", - [](const NodeAttrs& attrs){ - return std::vector >{{0, 1}}; - }) -.set_attr("FResourceRequest", - [](const NodeAttrs& attrs) { - return std::vector{ResourceRequest::kTempSpace}; - }) -.set_attr("FCompute", BinaryBroadcastBackwardUseIn); - -MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmax_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmax_scalar"}); - -MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmax_scalar) -.add_argument("scalar", "float", "scalar value") -.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) -.set_attr("FCompute", BinaryScalarOp::Backward); - -MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmin) -.set_attr("FCompute", BinaryBroadcastCompute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmin"}); - -NNVM_REGISTER_OP(_backward_npi_fmin) -.set_num_inputs(3) -.set_num_outputs(2) -.set_attr("TIsBackward", true) -.set_attr("FInplaceOption", - [](const NodeAttrs& attrs){ - return std::vector >{{0, 1}}; - }) -.set_attr("FResourceRequest", - [](const NodeAttrs& attrs) { - return std::vector{ResourceRequest::kTempSpace}; - }) -.set_attr("FCompute", BinaryBroadcastBackwardUseIn); - -MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmin_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmin_scalar"}); - -MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmin_scalar) -.add_argument("scalar", "float", "scalar value") -.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) -.set_attr("FCompute", BinaryScalarOp::Backward); - -MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmod) -.set_attr("FCompute", BinaryBroadcastCompute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmod"}); - -NNVM_REGISTER_OP(_backward_npi_fmod) -.set_num_inputs(3) -.set_num_outputs(2) -.set_attr("TIsBackward", true) -.set_attr("FInplaceOption", - [](const NodeAttrs& attrs){ - return std::vector >{{0, 1}}; - }) -.set_attr("FResourceRequest", - [](const NodeAttrs& attrs) { - return std::vector{ResourceRequest::kTempSpace}; - }) -.set_attr("FCompute", BinaryBroadcastBackwardUseIn); - -MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmod_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmod_scalar"}); - -MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmod_scalar) -.add_argument("scalar", "float", "scalar value") -.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) -.set_attr("FCompute", BinaryScalarOp::Backward); - -MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_rfmod_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute) -.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_rfmod_scalar"}); - -MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_rfmod_scalar) -.add_argument("scalar", "float", "scalar value") -.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) -.set_attr("FCompute", BinaryScalarOp::Backward); - } // namespace op } // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu index 8e3ec3db8784..8f135b3efd03 100644 --- a/src/operator/numpy/np_elemwise_broadcast_op_extended.cu +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended.cu @@ -116,50 +116,5 @@ NNVM_REGISTER_OP(_backward_npi_ldexp_scalar) NNVM_REGISTER_OP(_backward_npi_rldexp_scalar) .set_attr("FCompute", BinaryScalarOp::Backward); -NNVM_REGISTER_OP(_npi_fmax) -.set_attr("FCompute", BinaryBroadcastCompute); - -NNVM_REGISTER_OP(_backward_npi_fmax) -.set_attr("FCompute", BinaryBroadcastBackwardUseIn); - -NNVM_REGISTER_OP(_npi_fmax_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute); - -NNVM_REGISTER_OP(_backward_npi_fmax_scalar) -.set_attr("FCompute", BinaryScalarOp::Backward); - -NNVM_REGISTER_OP(_npi_fmin) -.set_attr("FCompute", BinaryBroadcastCompute); - -NNVM_REGISTER_OP(_backward_npi_fmin) -.set_attr("FCompute", BinaryBroadcastBackwardUseIn); - -NNVM_REGISTER_OP(_npi_fmin_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute); - -NNVM_REGISTER_OP(_backward_npi_fmin_scalar) -.set_attr("FCompute", BinaryScalarOp::Backward); - -NNVM_REGISTER_OP(_npi_fmod) -.set_attr("FCompute", BinaryBroadcastCompute); - -NNVM_REGISTER_OP(_backward_npi_fmod) -.set_attr("FCompute", BinaryBroadcastBackwardUseIn); - -NNVM_REGISTER_OP(_npi_fmod_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute); - -NNVM_REGISTER_OP(_backward_npi_fmod_scalar) -.set_attr("FCompute", BinaryScalarOp::Backward); - -NNVM_REGISTER_OP(_npi_rfmod_scalar) -.set_attr("FCompute", BinaryScalarOp::Compute); - -NNVM_REGISTER_OP(_backward_npi_rfmod_scalar) -.set_attr("FCompute", BinaryScalarOp::Backward); - } // namespace op } // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc b/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc new file mode 100644 index 000000000000..7455da139a14 --- /dev/null +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cc @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * Copyright (c) 2019 by Contributors + * \file np_elemwise_broadcast_op_extended_sec.cc + * \brief CPU Implementation of extended functions for elementwise numpy binary broadcast operator. (Second extended file) + */ + +#include "../../common/utils.h" +#include "./np_elemwise_broadcast_op.h" + +namespace mxnet { +namespace op { + +#define MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(name) \ + NNVM_REGISTER_OP(name) \ + .set_num_inputs(1) \ + .set_num_outputs(1) \ + .set_attr_parser([](NodeAttrs* attrs) { \ + attrs->parsed = std::stod(attrs->dict["scalar"]); \ + }) \ + .set_attr("FInferShape", ElemwiseShape<1, 1>) \ + .set_attr("FInferType", NumpyBinaryScalarType) \ + .set_attr("FInplaceOption", \ + [](const NodeAttrs& attrs){ \ + return std::vector >{{0, 0}}; \ + }) \ + .add_argument("data", "NDArray-or-Symbol", "source input") \ + .add_argument("scalar", "float", "scalar input") + +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmax) +.set_attr("FCompute", BinaryBroadcastCompute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmax"}); + +NNVM_REGISTER_OP(_backward_npi_fmax) +.set_num_inputs(3) +.set_num_outputs(2) +.set_attr("TIsBackward", true) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 1}}; + }) +.set_attr("FResourceRequest", + [](const NodeAttrs& attrs) { + return std::vector{ResourceRequest::kTempSpace}; + }) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmax_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmax_scalar"}); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmax_scalar) +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmin) +.set_attr("FCompute", BinaryBroadcastCompute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmin"}); + +NNVM_REGISTER_OP(_backward_npi_fmin) +.set_num_inputs(3) +.set_num_outputs(2) +.set_attr("TIsBackward", true) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 1}}; + }) +.set_attr("FResourceRequest", + [](const NodeAttrs& attrs) { + return std::vector{ResourceRequest::kTempSpace}; + }) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmin_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmin_scalar"}); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmin_scalar) +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + +MXNET_OPERATOR_REGISTER_BINARY_BROADCAST(_npi_fmod) +.set_attr("FCompute", BinaryBroadcastCompute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmod"}); + +NNVM_REGISTER_OP(_backward_npi_fmod) +.set_num_inputs(3) +.set_num_outputs(2) +.set_attr("TIsBackward", true) +.set_attr("FInplaceOption", + [](const NodeAttrs& attrs){ + return std::vector >{{0, 1}}; + }) +.set_attr("FResourceRequest", + [](const NodeAttrs& attrs) { + return std::vector{ResourceRequest::kTempSpace}; + }) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_fmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_fmod_scalar"}); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_fmod_scalar) +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + +MXNET_OPERATOR_REGISTER_NP_BINARY_SCALAR(_npi_rfmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute) +.set_attr("FGradient", ElemwiseGradUseIn{"_backward_npi_rfmod_scalar"}); + +MXNET_OPERATOR_REGISTER_BINARY(_backward_npi_rfmod_scalar) +.add_argument("scalar", "float", "scalar value") +.set_attr_parser([](NodeAttrs *attrs) { attrs->parsed = std::stod(attrs->dict["scalar"]); }) +.set_attr("FCompute", BinaryScalarOp::Backward); + +} // namespace op +} // namespace mxnet diff --git a/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cu b/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cu new file mode 100644 index 000000000000..fa2f3bf080c7 --- /dev/null +++ b/src/operator/numpy/np_elemwise_broadcast_op_extended_sec.cu @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * Copyright (c) 2019 by Contributors + * \file np_elemwise_broadcast_op_extended_sec.cu + * \brief GPU Implementation of extended functions for elementwise binary broadcast operator. (Second extended file) + */ + +#include "./np_elemwise_broadcast_op.h" + +namespace mxnet { +namespace op { + +NNVM_REGISTER_OP(_npi_fmax) +.set_attr("FCompute", BinaryBroadcastCompute); + +NNVM_REGISTER_OP(_backward_npi_fmax) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +NNVM_REGISTER_OP(_npi_fmax_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_fmax_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + +NNVM_REGISTER_OP(_npi_fmin) +.set_attr("FCompute", BinaryBroadcastCompute); + +NNVM_REGISTER_OP(_backward_npi_fmin) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +NNVM_REGISTER_OP(_npi_fmin_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_fmin_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + +NNVM_REGISTER_OP(_npi_fmod) +.set_attr("FCompute", BinaryBroadcastCompute); + +NNVM_REGISTER_OP(_backward_npi_fmod) +.set_attr("FCompute", BinaryBroadcastBackwardUseIn); + +NNVM_REGISTER_OP(_npi_fmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_fmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + +NNVM_REGISTER_OP(_npi_rfmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Compute); + +NNVM_REGISTER_OP(_backward_npi_rfmod_scalar) +.set_attr("FCompute", BinaryScalarOp::Backward); + +} // namespace op +} // namespace mxnet