This is an automated email from the ASF dual-hosted git repository.
haoj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git
The following commit(s) were added to refs/heads/master by this push:
new cf93bdc [Numpy] New FFIs for Operator: tile, trace, transpose (#18017)
cf93bdc is described below
commit cf93bdc3efc380180d74385d9e91c5034e0d7273
Author: Huang, Guangtai <[email protected]>
AuthorDate: Fri Apr 17 14:14:48 2020 +0800
[Numpy] New FFIs for Operator: tile, trace, transpose (#18017)
* init
* fix typo
* transpose
* add benchmark
* fix lint
---
benchmark/python/ffi/benchmark_ffi.py | 3 +
python/mxnet/_numpy_op_doc.py | 90 +----------------
python/mxnet/ndarray/numpy/_op.py | 101 ++++++++++++++++++-
python/mxnet/numpy/multiarray.py | 107 +++++++++++++++++++--
python/mxnet/symbol/numpy/_symbol.py | 59 +++++++++++-
src/api/operator/numpy/np_matrix_op.cc | 29 +++++-
.../{tensor/matrix_op.cc => numpy/np_trace_op.cc} | 49 ++++------
src/api/operator/tensor/matrix_op.cc | 25 ++++-
src/operator/numpy/np_matrix_op-inl.h | 5 +
src/operator/numpy/np_matrix_op.cc | 6 +-
src/operator/numpy/np_matrix_op.cu | 2 +-
src/operator/numpy/np_trace_op-inl.h | 10 ++
src/operator/numpy/np_trace_op.cc | 6 +-
src/operator/numpy/np_trace_op.cu | 4 +-
src/operator/tensor/matrix_op-inl.h | 5 +
15 files changed, 351 insertions(+), 150 deletions(-)
diff --git a/benchmark/python/ffi/benchmark_ffi.py
b/benchmark/python/ffi/benchmark_ffi.py
index c42e140..818e5a6 100644
--- a/benchmark/python/ffi/benchmark_ffi.py
+++ b/benchmark/python/ffi/benchmark_ffi.py
@@ -83,6 +83,9 @@ def prepare_workloads():
OpArgMngr.add_workload("linalg.tensorinv", pool['1x1'], ind=2)
OpArgMngr.add_workload("linalg.norm", pool['3x3'])
OpArgMngr.add_workload("linalg.tensorsolve", pool['1x1x1'], pool['1x1x1'],
(2, 0, 1))
+ OpArgMngr.add_workload("tile", pool['2x2'], 1)
+ OpArgMngr.add_workload("trace", pool['2x2'])
+ OpArgMngr.add_workload("transpose", pool['2x2'])
OpArgMngr.add_workload("split", pool['3x3'], (0, 1, 2), axis=1)
OpArgMngr.add_workload("argmax", pool['3x2'], axis=-1)
OpArgMngr.add_workload("argmin", pool['3x2'], axis=-1)
diff --git a/python/mxnet/_numpy_op_doc.py b/python/mxnet/_numpy_op_doc.py
index 857b87a..47d7545 100644
--- a/python/mxnet/_numpy_op_doc.py
+++ b/python/mxnet/_numpy_op_doc.py
@@ -37,7 +37,7 @@ def _npx_nonzero(a):
"""
Return the indices of the elements that are non-zero.
- Returns a ndarray with ndim is 2. Each row contains the indices
+ Returns a ndarray with ndim is 2. Each row contains the indices
of the non-zero elements. The values in `a` are always tested and returned
in
row-major, C-style order.
@@ -127,48 +127,6 @@ def _np_repeat(a, repeats, axis=None):
pass
-def _np_transpose(a, axes=None):
- """
- Permute the dimensions of an array.
-
- Parameters
- ----------
- a : ndarray
- Input array.
- axes : list of ints, optional
- By default, reverse the dimensions,
- otherwise permute the axes according to the values given.
-
- Returns
- -------
- p : ndarray
- a with its axes permuted.
-
- Notes
- -----
- This function differs from the original `numpy.transpose
-
<https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html>`_ in
- the following way(s):
-
- - only ndarray is accepted as valid input, python iterables are not
supported
- - the operator always returns an `ndarray` that does not share the memory
with the input
-
- Examples
- --------
- >>> x = np.arange(4).reshape((2,2))
- >>> x
- array([[0., 1.],
- [2., 3.]])
- >>> np.transpose(x)
- array([[0., 2.],
- [1., 3.]])
- >>> x = np.ones((1, 2, 3))
- >>> np.transpose(x, (1, 0, 2)).shape
- (2, 1, 3)
- """
- pass
-
-
def _np_dot(a, b, out=None):
"""
Dot product of two arrays. Specifically,
@@ -339,52 +297,6 @@ def _np_reshape(a, newshape, order='C', out=None):
"""
-def _np_trace(a, offset=0, axis1=0, axis2=1, out=None):
- """
- Return the sum along diagonals of the array.
- If `a` is 2-D, the sum along its diagonal with the given offset
- is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
- If `a` has more than two dimensions, then the axes specified by axis1 and
- axis2 are used to determine the 2-D sub-arrays whose traces are returned.
- The shape of the resulting array is the same as that of `a` with `axis1`
- and `axis2` removed.
-
- Parameters
- ----------
- a : ndarray
- Input array, from which the diagonals are taken.
- offset : int, optional
- Offset of the diagonal from the main diagonal. Can be both positive
- and negative. Defaults to 0.
- axis1, axis2 : int, optional
- Axes to be used as the first and second axis of the 2-D sub-arrays
- from which the diagonals should be taken. Defaults are the first two
- axes of `a`.
- out : ndarray, optional
- Array into which the output is placed. It must be of the right shape
- and right type to hold the output.
-
- Returns
- -------
- sum_along_diagonals : ndarray
- If `a` is 2-D, the sum along the diagonal is returned. If `a` has
- larger dimensions, then an array of sums along diagonals is returned.
-
- Examples
- --------
- >>> a = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
- >>> np.trace(a)
- array(3.)
- >>> a = np.arange(8).reshape((2, 2, 2))
- >>> np.trace(a)
- array([6., 8.])
- >>> a = np.arange(24).reshape((2, 2, 2, 3))
- >>> np.trace(a).shape
- (2, 3)
- """
- pass
-
-
def _np_squeeze(a, axis=None, out=None):
"""
Remove single-dimensional entries from the shape of an array.
diff --git a/python/mxnet/ndarray/numpy/_op.py
b/python/mxnet/ndarray/numpy/_op.py
index 1a66abb..06b8d5f 100644
--- a/python/mxnet/ndarray/numpy/_op.py
+++ b/python/mxnet/ndarray/numpy/_op.py
@@ -31,7 +31,7 @@ from ..ndarray import NDArray
__all__ = ['shape', 'zeros', 'zeros_like', 'ones', 'ones_like', 'full',
'full_like', 'empty_like', 'invert', 'delete',
'add', 'broadcast_to', 'subtract', 'multiply', 'divide', 'mod',
'remainder', 'fmod',
- 'power', 'bitwise_not',
+ 'power', 'bitwise_not', 'trace', 'transpose',
'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',
@@ -2095,6 +2095,53 @@ def triu(m, k=0):
return _api_internal.triu(m, k)
+@set_module('mxnet.ndarray.numpy')
+def trace(a, offset=0, axis1=0, axis2=1, out=None):
+ """
+ Return the sum along diagonals of the array.
+ If `a` is 2-D, the sum along its diagonal with the given offset
+ is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
+ If `a` has more than two dimensions, then the axes specified by axis1 and
+ axis2 are used to determine the 2-D sub-arrays whose traces are returned.
+ The shape of the resulting array is the same as that of `a` with `axis1`
+ and `axis2` removed.
+
+ Parameters
+ ----------
+ a : ndarray
+ Input array, from which the diagonals are taken.
+ offset : int, optional
+ Offset of the diagonal from the main diagonal. Can be both positive
+ and negative. Defaults to 0.
+ axis1, axis2 : int, optional
+ Axes to be used as the first and second axis of the 2-D sub-arrays
+ from which the diagonals should be taken. Defaults are the first two
+ axes of `a`.
+ out : ndarray, optional
+ Array into which the output is placed. It must be of the right shape
+ and right type to hold the output.
+
+ Returns
+ -------
+ sum_along_diagonals : ndarray
+ If `a` is 2-D, the sum along the diagonal is returned. If `a` has
+ larger dimensions, then an array of sums along diagonals is returned.
+
+ Examples
+ --------
+ >>> a = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+ >>> np.trace(a)
+ array(3.)
+ >>> a = np.arange(8).reshape((2, 2, 2))
+ >>> np.trace(a)
+ array([6., 8.])
+ >>> a = np.arange(24).reshape((2, 2, 2, 3))
+ >>> np.trace(a).shape
+ (2, 3)
+ """
+ return _api_internal.trace(a, offset, axis1, axis2, out)
+
+
def _unary_func_helper(x, fn_array, fn_scalar, out=None, **kwargs):
"""Helper function for unary operators with kwargs.
@@ -3748,7 +3795,7 @@ def tile(A, reps):
>>> np.tile(b, 2)
array([[1., 2., 1., 2.],
[3., 4., 3., 4.]])
- >>> np.(b, (2, 1))
+ >>> np.tile(b, (2, 1))
array([[1., 2.],
[3., 4.],
[1., 2.],
@@ -3767,7 +3814,55 @@ def tile(A, reps):
array([2, 2, 2]) # repeating integer `2`
"""
- return _unary_func_helper(A, _npi.tile, _np.tile, reps=reps)
+ if isinstance(A, numeric_types):
+ return _np.tile(A, reps)
+ elif isinstance(A, NDArray):
+ return _api_internal.tile(A, reps)
+ else:
+ raise TypeError('type {} not supported'.format(str(type(A))))
+
+
+@set_module('mxnet.ndarray.numpy')
+def transpose(a, axes=None):
+ """
+ Permute the dimensions of an array.
+
+ Parameters
+ ----------
+ a : ndarray
+ Input array.
+ axes : list of ints, optional
+ By default, reverse the dimensions,
+ otherwise permute the axes according to the values given.
+
+ Returns
+ -------
+ p : ndarray
+ a with its axes permuted.
+
+ Notes
+ -----
+ This function differs from the original `numpy.transpose
+
<https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html>`_ in
+ the following way(s):
+
+ - only ndarray is accepted as valid input, python iterables are not
supported
+ - the operator always returns an `ndarray` that does not share the memory
with the input
+
+ Examples
+ --------
+ >>> x = np.arange(4).reshape((2,2))
+ >>> x
+ array([[0., 1.],
+ [2., 3.]])
+ >>> np.transpose(x)
+ array([[0., 2.],
+ [1., 3.]])
+ >>> x = np.ones((1, 2, 3))
+ >>> np.transpose(x, (1, 0, 2)).shape
+ (2, 1, 3)
+ """
+ return _api_internal.transpose(a, axes)
# pylint: disable=redefined-outer-name
diff --git a/python/mxnet/numpy/multiarray.py b/python/mxnet/numpy/multiarray.py
index 2d6a788..99a6744 100644
--- a/python/mxnet/numpy/multiarray.py
+++ b/python/mxnet/numpy/multiarray.py
@@ -55,7 +55,7 @@ from . import fallback
__all__ = ['ndarray', 'empty', 'empty_like', 'array', 'shape', 'median',
'zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like',
'all', 'any', 'broadcast_to',
'add', 'subtract', 'multiply', 'divide', 'mod', 'remainder',
'fmod', 'power', 'bitwise_not',
- 'delete',
+ 'delete', 'trace', 'transpose',
'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',
@@ -1730,13 +1730,10 @@ class ndarray(NDArray):
"""
raise AttributeError('mxnet.numpy.ndarray object has no attribute
expand_dims')
- def tile(self, *args, **kwargs):
- """Convenience fluent method for :py:func:`tile`.
-
- The arguments are the same as for :py:func:`tile`, with
- this array as data.
- """
- raise AttributeError('mxnet.numpy.ndarray object has no attribute
tile')
+ def tile(self, reps): # pylint: disable=arguments-differ
+ """Construct an array by repeating A the number of times given by reps.
+ Refer to `mxnet.numpy.tile` for full documentation."""
+ return tile(self, reps=reps)
def transpose(self, *axes): # pylint: disable=arguments-differ
"""Permute the dimensions of an array."""
@@ -1747,7 +1744,7 @@ class ndarray(NDArray):
axes = axes[0]
elif axes[0] is None:
axes = None
- return _mx_np_op.transpose(self, axes=axes)
+ return transpose(self, axes=axes)
def flip(self, *args, **kwargs):
"""Convenience fluent method for :py:func:`flip`.
@@ -5477,7 +5474,7 @@ def tile(A, reps):
>>> np.tile(b, 2)
array([[1., 2., 1., 2.],
[3., 4., 3., 4.]])
- >>> np.(b, (2, 1))
+ >>> np.tile(b, (2, 1))
array([[1., 2.],
[3., 4.],
[1., 2.],
@@ -5500,6 +5497,96 @@ def tile(A, reps):
@set_module('mxnet.numpy')
+def trace(a, offset=0, axis1=0, axis2=1, out=None):
+ """
+ Return the sum along diagonals of the array.
+ If `a` is 2-D, the sum along its diagonal with the given offset
+ is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
+ If `a` has more than two dimensions, then the axes specified by axis1 and
+ axis2 are used to determine the 2-D sub-arrays whose traces are returned.
+ The shape of the resulting array is the same as that of `a` with `axis1`
+ and `axis2` removed.
+
+ Parameters
+ ----------
+ a : ndarray
+ Input array, from which the diagonals are taken.
+ offset : int, optional
+ Offset of the diagonal from the main diagonal. Can be both positive
+ and negative. Defaults to 0.
+ axis1, axis2 : int, optional
+ Axes to be used as the first and second axis of the 2-D sub-arrays
+ from which the diagonals should be taken. Defaults are the first two
+ axes of `a`.
+ out : ndarray, optional
+ Array into which the output is placed. It must be of the right shape
+ and right type to hold the output.
+
+ Returns
+ -------
+ sum_along_diagonals : ndarray
+ If `a` is 2-D, the sum along the diagonal is returned. If `a` has
+ larger dimensions, then an array of sums along diagonals is returned.
+
+ Examples
+ --------
+ >>> a = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+ >>> np.trace(a)
+ array(3.)
+ >>> a = np.arange(8).reshape((2, 2, 2))
+ >>> np.trace(a)
+ array([6., 8.])
+ >>> a = np.arange(24).reshape((2, 2, 2, 3))
+ >>> np.trace(a).shape
+ (2, 3)
+ """
+ return _mx_nd_np.trace(a, offset, axis1, axis2, out)
+
+
+@set_module('mxnet.numpy')
+def transpose(a, axes=None):
+ """
+ Permute the dimensions of an array.
+
+ Parameters
+ ----------
+ a : ndarray
+ Input array.
+ axes : list of ints, optional
+ By default, reverse the dimensions,
+ otherwise permute the axes according to the values given.
+
+ Returns
+ -------
+ p : ndarray
+ a with its axes permuted.
+
+ Notes
+ -----
+ This function differs from the original `numpy.transpose
+
<https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html>`_ in
+ the following way(s):
+
+ - only ndarray is accepted as valid input, python iterables are not
supported
+ - the operator always returns an `ndarray` that does not share the memory
with the input
+
+ Examples
+ --------
+ >>> x = np.arange(4).reshape((2,2))
+ >>> x
+ array([[0., 1.],
+ [2., 3.]])
+ >>> np.transpose(x)
+ array([[0., 2.],
+ [1., 3.]])
+ >>> x = np.ones((1, 2, 3))
+ >>> np.transpose(x, (1, 0, 2)).shape
+ (2, 1, 3)
+ """
+ return _mx_nd_np.transpose(a, axes)
+
+
+@set_module('mxnet.numpy')
def tril(m, k=0):
r"""
Lower triangle of an array.
diff --git a/python/mxnet/symbol/numpy/_symbol.py
b/python/mxnet/symbol/numpy/_symbol.py
index 8b31c8e..5951865 100644
--- a/python/mxnet/symbol/numpy/_symbol.py
+++ b/python/mxnet/symbol/numpy/_symbol.py
@@ -37,7 +37,7 @@ except ImportError:
__all__ = ['zeros', 'zeros_like', 'ones', 'ones_like', 'full', 'full_like',
'empty_like', 'bitwise_not', 'invert',
'delete', 'add', 'broadcast_to', 'subtract', 'multiply', 'divide',
'mod', 'remainder', 'fmod',
- 'power', 'arctan2',
+ 'power', 'arctan2', 'trace', 'transpose',
'sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh', 'log10', 'sqrt',
'cbrt', 'abs', 'absolute', 'fabs', 'exp',
'expm1', 'arcsin', 'arccos', 'arctan', 'sign', 'log', 'degrees',
'log2', 'log1p', 'matmul', 'median',
'rint', 'radians', 'reciprocal', 'square', 'negative', 'fix',
'ceil', 'floor', 'histogram', 'insert',
@@ -653,7 +653,7 @@ class _Symbol(Symbol):
axes = axes[0]
elif axes[0] is None:
axes = None
- return _mx_np_op.transpose(self, axes=axes)
+ return transpose(self, axes=axes)
def flip(self, *args, **kwargs):
"""Convenience fluent method for :py:func:`flip`.
@@ -2308,6 +2308,61 @@ def tril_indices(n, k=0, m=None):
return _npi.tril_indices(n, k, m)
+@set_module('mxnet.symbol.numpy')
+def trace(a, offset=0, axis1=0, axis2=1, out=None):
+ """
+ Return the sum along diagonals of the array.
+ If `a` is 2-D, the sum along its diagonal with the given offset
+ is returned, i.e., the sum of elements ``a[i,i+offset]`` for all i.
+ If `a` has more than two dimensions, then the axes specified by axis1 and
+ axis2 are used to determine the 2-D sub-arrays whose traces are returned.
+ The shape of the resulting array is the same as that of `a` with `axis1`
+ and `axis2` removed.
+
+ Parameters
+ ----------
+ a : _Symbol
+ Input array, from which the diagonals are taken.
+ offset : int, optional
+ Offset of the diagonal from the main diagonal. Can be both positive
+ and negative. Defaults to 0.
+ axis1, axis2 : int, optional
+ Axes to be used as the first and second axis of the 2-D sub-arrays
+ from which the diagonals should be taken. Defaults are the first two
+ axes of `a`.
+ out : _Symbol
+ Dummy parameter to keep the consistency with the ndarray counterpart.
+
+ Returns
+ -------
+ sum_along_diagonals : _Symbol
+ If `a` is 2-D, the sum along the diagonal is returned. If `a` has
+ larger dimensions, then an array of sums along diagonals is returned.
+ """
+ return _npi.trace(a, offset=offset, axis1=axis1, axis2=axis2, out=out)
+
+
+@set_module('mxnet.symbol.numpy')
+def transpose(a, axes=None):
+ """
+ Permute the dimensions of an array.
+
+ Parameters
+ ----------
+ a : _Symbol
+ Input array.
+ axes : list of ints, optional
+ By default, reverse the dimensions,
+ otherwise permute the axes according to the values given.
+
+ Returns
+ -------
+ p : _Symbol
+ a with its axes permuted.
+ """
+ return _npi.transpose(a, axes=axes)
+
+
def _unary_func_helper(x, fn_array, fn_scalar, out=None, **kwargs):
"""Helper function for unary operators.
diff --git a/src/api/operator/numpy/np_matrix_op.cc
b/src/api/operator/numpy/np_matrix_op.cc
index 998823d..58ee563 100644
--- a/src/api/operator/numpy/np_matrix_op.cc
+++ b/src/api/operator/numpy/np_matrix_op.cc
@@ -6,9 +6,9 @@
* 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
@@ -19,7 +19,7 @@
/*!
* \file np_matrix_op.cc
- * \brief Implementation of the API of functions in
src/operator/tensor/matrix_op.cc
+ * \brief Implementation of the API of functions in
src/operator/numpy/np_matrix_op.cc
*/
#include <mxnet/api_registry.h>
#include <mxnet/runtime/packed_func.h>
@@ -31,6 +31,29 @@
namespace mxnet {
+MXNET_REGISTER_API("_npi.transpose")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+ using namespace runtime;
+ static const nnvm::Op* op = Op::Get("_npi_transpose");
+ nnvm::NodeAttrs attrs;
+ op::NumpyTransposeParam param;
+ if (args[1].type_code() == kNull) {
+ param.axes = TShape(-1, 0);
+ } else if (args[1].type_code() == kDLInt) {
+ param.axes = TShape(1, args[1].operator int64_t());
+ } else {
+ param.axes = TShape(args[1].operator ObjectRef());
+ }
+ attrs.parsed = std::move(param);
+ attrs.op = op;
+ SetAttrDict<op::NumpyTransposeParam>(&attrs);
+ NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+ int num_inputs = 1;
+ int num_outputs = 0;
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs,
nullptr);
+ *ret = ndoutputs[0];
+});
+
MXNET_REGISTER_API("_npi.expand_dims")
.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
using namespace runtime;
diff --git a/src/api/operator/tensor/matrix_op.cc
b/src/api/operator/numpy/np_trace_op.cc
similarity index 61%
copy from src/api/operator/tensor/matrix_op.cc
copy to src/api/operator/numpy/np_trace_op.cc
index ed91b09..2979d21 100644
--- a/src/api/operator/tensor/matrix_op.cc
+++ b/src/api/operator/numpy/np_trace_op.cc
@@ -6,9 +6,9 @@
* 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
@@ -18,51 +18,36 @@
*/
/*!
- * \file matrix_op.cc
- * \brief Implementation of the API of functions in
src/operator/tensor/matrix_op.cc
+ * \file np_trace_op.cc
+ * \brief Implementation of the API of functions in
src/operator/numpy/np_trace_op.cc
*/
#include <mxnet/api_registry.h>
#include <mxnet/runtime/packed_func.h>
#include "../utils.h"
-#include "../../../operator/tensor/matrix_op-inl.h"
+#include "../../../operator/numpy/np_trace_op-inl.h"
namespace mxnet {
-MXNET_REGISTER_API("_npi.clip")
+MXNET_REGISTER_API("_npi.trace")
.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
using namespace runtime;
- const nnvm::Op* op = Op::Get("_npi_clip");
+ const nnvm::Op* op = Op::Get("_npi_trace");
nnvm::NodeAttrs attrs;
- op::ClipParam param;
- NDArray* inputs[1];
-
- if (args[0].type_code() != kNull) {
- inputs[0] = args[0].operator mxnet::NDArray *();
- }
-
- if (args[1].type_code() != kNull) {
- param.a_min = args[1].operator double();
- } else {
- param.a_min = -INFINITY;
- }
-
- if (args[2].type_code() != kNull) {
- param.a_max = args[2].operator double();
- } else {
- param.a_max = INFINITY;
- }
-
+ op::NumpyTraceParam param;
+ param.offset = args[1].operator int64_t();
+ param.axis1 = args[2].operator int64_t();
+ param.axis2 = args[3].operator int64_t();
attrs.parsed = param;
attrs.op = op;
- SetAttrDict<op::ClipParam>(&attrs);
-
- NDArray* out = args[3].operator mxnet::NDArray*();
+ SetAttrDict<op::NumpyTraceParam>(&attrs);
+ NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+ int num_inputs = 1;
+ NDArray* out = args[4].operator mxnet::NDArray*();
NDArray** outputs = out == nullptr ? nullptr : &out;
- // set the number of outputs provided by the `out` arugment
int num_outputs = out != nullptr;
- auto ndoutputs = Invoke(op, &attrs, 1, inputs, &num_outputs, outputs);
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs,
outputs);
if (out) {
- *ret = PythonArg(3);
+ *ret = PythonArg(4);
} else {
*ret = ndoutputs[0];
}
diff --git a/src/api/operator/tensor/matrix_op.cc
b/src/api/operator/tensor/matrix_op.cc
index ed91b09..6134428 100644
--- a/src/api/operator/tensor/matrix_op.cc
+++ b/src/api/operator/tensor/matrix_op.cc
@@ -6,9 +6,9 @@
* 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
@@ -68,4 +68,25 @@ MXNET_REGISTER_API("_npi.clip")
}
});
+MXNET_REGISTER_API("_npi.tile")
+.set_body([](runtime::MXNetArgs args, runtime::MXNetRetValue* ret) {
+ using namespace runtime;
+ const nnvm::Op* op = Op::Get("_npi_tile");
+ nnvm::NodeAttrs attrs;
+ op::TileParam param;
+ if (args[1].type_code() == kDLInt) {
+ param.reps = Tuple<int>(1, args[1].operator int64_t());
+ } else {
+ param.reps = Tuple<int>(args[1].operator ObjectRef());
+ }
+ attrs.parsed = std::move(param);
+ attrs.op = op;
+ SetAttrDict<op::TileParam>(&attrs);
+ int num_outputs = 0;
+ NDArray* inputs[] = {args[0].operator mxnet::NDArray*()};
+ int num_inputs = 1;
+ auto ndoutputs = Invoke(op, &attrs, num_inputs, inputs, &num_outputs,
nullptr);
+ *ret = ndoutputs[0];
+});
+
} // namespace mxnet
diff --git a/src/operator/numpy/np_matrix_op-inl.h
b/src/operator/numpy/np_matrix_op-inl.h
index 09eb10c..4d73fae 100644
--- a/src/operator/numpy/np_matrix_op-inl.h
+++ b/src/operator/numpy/np_matrix_op-inl.h
@@ -47,6 +47,11 @@ struct NumpyTransposeParam : public
dmlc::Parameter<NumpyTransposeParam> {
.describe("By default, reverse the dimensions, otherwise permute "
"the axes according to the values given.");
}
+ void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+ std::ostringstream axes_s;
+ axes_s << axes;
+ (*dict)["axes"] = axes_s.str();
+ }
};
struct NumpyVstackParam : public dmlc::Parameter<NumpyVstackParam> {
diff --git a/src/operator/numpy/np_matrix_op.cc
b/src/operator/numpy/np_matrix_op.cc
index f47a575..902db89 100644
--- a/src/operator/numpy/np_matrix_op.cc
+++ b/src/operator/numpy/np_matrix_op.cc
@@ -105,7 +105,7 @@ bool NumpyTransposeShape(const nnvm::NodeAttrs& attrs,
return shape_is_known(*in_attrs) && shape_is_known(*out_attrs);
}
-NNVM_REGISTER_OP(_np_transpose)
+NNVM_REGISTER_OP(_npi_transpose)
.set_num_inputs(1)
.set_num_outputs(1)
.set_attr_parser(ParamParser<NumpyTransposeParam>)
@@ -126,9 +126,9 @@ NNVM_REGISTER_OP(_np_transpose)
}
std::ostringstream os;
os << axes;
- return MakeNonlossGradNode("_np_transpose", n, ograds, {}, {{"axes",
os.str()}});
+ return MakeNonlossGradNode("_npi_transpose", n, ograds, {}, {{"axes",
os.str()}});
} else {
- return MakeNonlossGradNode("_np_transpose", n, ograds, {},
+ return MakeNonlossGradNode("_npi_transpose", n, ograds, {},
std::unordered_map<std::string,
std::string>());
}
})
diff --git a/src/operator/numpy/np_matrix_op.cu
b/src/operator/numpy/np_matrix_op.cu
index f919bb5..7b525d1 100644
--- a/src/operator/numpy/np_matrix_op.cu
+++ b/src/operator/numpy/np_matrix_op.cu
@@ -29,7 +29,7 @@
namespace mxnet {
namespace op {
-NNVM_REGISTER_OP(_np_transpose)
+NNVM_REGISTER_OP(_npi_transpose)
.set_attr<FCompute>("FCompute<gpu>", NumpyTranspose<gpu>);
NNVM_REGISTER_OP(_np_reshape)
diff --git a/src/operator/numpy/np_trace_op-inl.h
b/src/operator/numpy/np_trace_op-inl.h
index 741c20b..ede7d37 100644
--- a/src/operator/numpy/np_trace_op-inl.h
+++ b/src/operator/numpy/np_trace_op-inl.h
@@ -28,6 +28,7 @@
#include <dmlc/parameter.h>
#include <mxnet/operator_util.h>
#include <vector>
+#include <string>
#include <utility>
#include <algorithm>
#include "../mxnet_op.h"
@@ -54,6 +55,15 @@ struct NumpyTraceParam: public
dmlc::Parameter<NumpyTraceParam> {
.describe("Axes to be used as the second axis of the 2-D sub-arrays "
"from which the diagonals should be taken. Defaults to 1.");
}
+ void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+ std::ostringstream offset_s, axis1_s, axis2_s;
+ offset_s << offset;
+ axis1_s << axis1;
+ axis2_s << axis2;
+ (*dict)["offset"] = offset_s.str();
+ (*dict)["axis1"] = axis1_s.str();
+ (*dict)["axis2"] = axis2_s.str();
+ }
};
template<int ndim, int req, bool back>
diff --git a/src/operator/numpy/np_trace_op.cc
b/src/operator/numpy/np_trace_op.cc
index d97ac30..e6a1201 100644
--- a/src/operator/numpy/np_trace_op.cc
+++ b/src/operator/numpy/np_trace_op.cc
@@ -54,7 +54,7 @@ inline bool NumpyTraceOpShape(const nnvm::NodeAttrs& attrs,
DMLC_REGISTER_PARAMETER(NumpyTraceParam);
-NNVM_REGISTER_OP(_np_trace)
+NNVM_REGISTER_OP(_npi_trace)
.describe(R"code(Computes the sum of the diagonal elements of a matrix.
Input is a tensor *A* of dimension *n >= 2*.
@@ -83,11 +83,11 @@ Examples::
.set_attr<mxnet::FInferShape>("FInferShape", NumpyTraceOpShape)
.set_attr<nnvm::FInferType>("FInferType", ElemwiseType<1, 1>)
.set_attr<FCompute>("FCompute<cpu>", NumpyTraceOpForward<cpu>)
-.set_attr<nnvm::FGradient>("FGradient",
ElemwiseGradUseNone{"_backward_np_trace"})
+.set_attr<nnvm::FGradient>("FGradient",
ElemwiseGradUseNone{"_backward_npi_trace"})
.add_argument("data", "NDArray-or-Symbol", "Input ndarray")
.add_arguments(NumpyTraceParam::__FIELDS__());
-NNVM_REGISTER_OP(_backward_np_trace)
+NNVM_REGISTER_OP(_backward_npi_trace)
.set_attr_parser(ParamParser<NumpyTraceParam>)
.set_num_inputs(1)
.set_num_outputs(1)
diff --git a/src/operator/numpy/np_trace_op.cu
b/src/operator/numpy/np_trace_op.cu
index 220e4ae..5ec2913 100644
--- a/src/operator/numpy/np_trace_op.cu
+++ b/src/operator/numpy/np_trace_op.cu
@@ -26,10 +26,10 @@
namespace mxnet {
namespace op {
-NNVM_REGISTER_OP(_np_trace)
+NNVM_REGISTER_OP(_npi_trace)
.set_attr<FCompute>("FCompute<gpu>", NumpyTraceOpForward<gpu>);
-NNVM_REGISTER_OP(_backward_np_trace)
+NNVM_REGISTER_OP(_backward_npi_trace)
.set_attr<FCompute>("FCompute<gpu>", NumpyTraceOpBackward<gpu>);
} // namespace op
diff --git a/src/operator/tensor/matrix_op-inl.h
b/src/operator/tensor/matrix_op-inl.h
index 821fa85..19d713d 100644
--- a/src/operator/tensor/matrix_op-inl.h
+++ b/src/operator/tensor/matrix_op-inl.h
@@ -1925,6 +1925,11 @@ struct TileParam : public dmlc::Parameter<TileParam> {
" If a.ndim < d, a is promoted to be d-dimensional by
prepending new axes."
" If a.ndim > d, reps is promoted to a.ndim by pre-pending 1's
to it.");
}
+ void SetAttrDict(std::unordered_map<std::string, std::string>* dict) {
+ std::ostringstream reps_s;
+ reps_s << reps;
+ (*dict)["reps"] = reps_s.str();
+ }
};
inline bool TileOpShape(const nnvm::NodeAttrs& attrs,