We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG]some bugs about `mt.split`
## Describe the bug
I find `mt.split` does not work well when i try to use `mt.unique` and `mt.split` to group a sorted array.

I find two bugs:
- `mt.split` does not support tuple and array as the first argument. Could you consider supporting this for convenience of usage? See below:
```
>>> mt.split((1,1,1,2,2,3), (3,5))

~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in split(ary, indices_or_sections, axis)
    199 
    200     """
--> 201     return _split(ary, indices_or_sections, axis=axis, is_split=True)

~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in _split(a, indices_or_sections, axis, is_split)
    127 
    128 def _split(a, indices_or_sections, axis=0, is_split=False):
--> 129     op = TensorSplit(axis=axis, dtype=a.dtype)
    130     return op(a, indices_or_sections, is_split=is_split)
    131 

AttributeError: 'list' object has no attribute 'dtype'

>>> mt.split([1,1,1,2,2,3], (3,5))

~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in split(ary, indices_or_sections, axis)
    199 
    200     """
--> 201     return _split(ary, indices_or_sections, axis=axis, is_split=True)

~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in _split(a, indices_or_sections, axis, is_split)
    127 
    128 def _split(a, indices_or_sections, axis=0, is_split=False):
--> 129     op = TensorSplit(axis=axis, dtype=a.dtype)
    130     return op(a, indices_or_sections, is_split=is_split)
    131 

AttributeError: 'tuple' object has no attribute 'dtype'
```
- this one seems weird. I obtain the index from `mt.unique` with a sorted array and argument `return_index` True. When I passed the executed result of a slice of this index as the second arguments of `mt.split`, the returned sub-tensors all have nan shape and i cannot execute the sub-tensor to get the value. If i passed list, tuple or a `mt.array` with literal list, `mt.split` works well. See below for details:
```
In [67]: p = (1,1,1,2,2,3)                                                                                                                                                                           

In [68]: unique, index = mt.unique(p, return_index=True)                                                                                                                                             

In [69]: index.execute()                                                                                                                                                                             
Out[69]: array([0, 3, 5])

In [70]: index1 = index[1:].execute()                                                                                                                                                                

In [71]: index1                                                                                                                                                                                      
Out[71]: array([3, 5])

In [72]: mt.split(mt.array(p), index1)                                                                                                                                                               
Out[72]: 
(Tensor <op=TensorSplit, shape=(nan,), key=61fbfb5330abb901e5b56269d6fbad5f,
 Tensor <op=TensorSplit, shape=(nan,), key=f3a4dc180f9350bb7ac5ffcb18abd297,
 Tensor <op=TensorSplit, shape=(nan,), key=65fadafe692317ee6ba59630753cafb5)

In [73]: mt.split(mt.array(p), mt.array((3,5)))                                                                                                                                                      
Out[73]: 
(Tensor <op=TensorSplit, shape=(3,), key=6f04c920a336bb8ae733b50c91da57ba,
 Tensor <op=TensorSplit, shape=(2,), key=11ef35d05602119da39c0924a6787245,
 Tensor <op=TensorSplit, shape=(1,), key=dd1c7e9460185aef0991c5cfa8e77823)
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mars/tensor/base/split.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # Copyright 1999-2020 Alibaba Group Holding Ltd.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 import numpy as np
18 
19 from ... import opcodes as OperandDef
20 from ...serialize import KeyField, AnyField, Int32Field
21 from ...lib.sparse.core import get_array_module
22 from ...core import ExecutableTuple
23 from ..core import Tensor
24 from ..utils import calc_sliced_size
25 from ..operands import TensorHasInput, TensorOperandMixin
26 
27 
28 class TensorSplit(TensorHasInput, TensorOperandMixin):
29     _op_type_ = OperandDef.ARRAY_SPLIT
30 
31     _input = KeyField('input')
32     _indices_or_sections = AnyField('indices_or_sections')
33     _axis = Int32Field('axis')
34 
35     def __init__(self, axis=None, dtype=None, **kw):
36         super().__init__(_axis=axis, _dtype=dtype, **kw)
37 
38     @property
39     def indices_or_sections(self):
40         return self._indices_or_sections
41 
42     @property
43     def axis(self):
44         return getattr(self, '_axis', 0)
45 
46     @property
47     def output_limit(self):
48         return float('inf')
49 
50     def _set_inputs(self, inputs):
51         super()._set_inputs(inputs)
52         self._input = self._inputs[0]
53         if len(self._inputs) > 1:
54             self._indices_or_sections = self._inputs[1]
55 
56     def __call__(self, a, indices_or_sections, is_split=False):
57         axis = self._axis
58         size = a.shape[axis]
59         if np.isnan(size):
60             raise ValueError('cannot split array with unknown shape, '
61                              'call `.execute()` on input tensor first')
62 
63         if isinstance(indices_or_sections, Tensor) and hasattr(indices_or_sections.op, 'data') and \
64                 indices_or_sections.op.data is not None:
65             indices_or_sections = indices_or_sections.op.data
66 
67         try:
68             indices_or_sections = int(indices_or_sections)
69             if is_split:
70                 if size % indices_or_sections:
71                     raise ValueError('tensor split does not result in an equal division')
72                 nparts = indices_or_sections
73                 nsplit = (size // indices_or_sections,) * nparts
74             else:
75                 nparts = indices_or_sections
76                 if size % indices_or_sections == 0:
77                     nsplit = (size // indices_or_sections,) * nparts
78                 else:
79                     nsplit = (size // indices_or_sections + 1,) * (size % indices_or_sections) + \
80                              (size // indices_or_sections,) * (size - size % indices_or_sections)
81         except TypeError:
82             if isinstance(indices_or_sections, Tensor):
83                 nparts = indices_or_sections.shape[0] + 1
84                 nsplit = (np.nan,) * nparts
85             else:
86                 ind = indices_or_sections = get_array_module(indices_or_sections).asarray(indices_or_sections)
87                 if indices_or_sections.ndim != 1 or not np.issubdtype(indices_or_sections.dtype, np.integer):
88                     raise TypeError('slice indices must be integers or None')
89                 nparts = indices_or_sections.shape[0] + 1
90                 get = lambda i: None if i < 0 or i >= len(ind) else ind[i]
91                 nsplit = [calc_sliced_size(size, slice(get(j - 1), get(j))) for j in range(nparts)]
92 
93         inputs = [a]
94         if isinstance(indices_or_sections, Tensor):
95             inputs.append(indices_or_sections)
96         else:
97             self._indices_or_sections = indices_or_sections
98 
99         kws = [{'i': i, 'shape': a.shape[:axis] + (nsplit[i],) + a.shape[axis + 1:], 'order': a.order}
100                for i in range(nparts)]
101         return ExecutableTuple(self.new_tensors(inputs, kws=kws, output_limit=nparts))
102 
103     @classmethod
104     def tile(cls, op):
105         in_tensor = op.input
106         splits = op.outputs
107         axis = op.axis
108 
109         if any(np.isnan(s.shape[axis]) for s in splits):
110             # TODO(xuye.qin): when iterative tiling is ready and we can retrieve data from context,
111             # this function would be available
112             raise ValueError(f'Tensor chunk sizes are unknown: {splits}')
113 
114         acc_shapes = np.cumsum([s.shape[axis] for s in splits])
115         out_kws = [dict() for _ in splits]
116         for i, split in enumerate(splits):
117             slc = slice(0 if i == 0 else acc_shapes[i - 1], acc_shapes[i])
118             new_s = in_tensor[(slice(None),) * axis + (slc,)]._inplace_tile()
119             out_kws[i]['chunks'] = new_s.chunks
120             out_kws[i]['nsplits'] = new_s.nsplits
121             out_kws[i]['shape'] = split.shape
122             out_kws[i]['order'] = op.outputs[i].order
123 
124         new_op = op.copy()
125         return new_op.new_tensors(op.inputs, kws=out_kws, output_limit=len(out_kws))
126 
127 
128 def _split(a, indices_or_sections, axis=0, is_split=False):
129     op = TensorSplit(axis=axis, dtype=a.dtype)
130     return op(a, indices_or_sections, is_split=is_split)
131 
132 
133 def split(ary, indices_or_sections, axis=0):
134     """
135     Split a tensor into multiple sub-tensors.
136 
137     Parameters
138     ----------
139     ary : Tensor
140         Tensor to be divided into sub-tensors.
141     indices_or_sections : int or 1-D tensor
142         If `indices_or_sections` is an integer, N, the array will be divided
143         into N equal tensors along `axis`.  If such a split is not possible,
144         an error is raised.
145 
146         If `indices_or_sections` is a 1-D tensor of sorted integers, the entries
147         indicate where along `axis` the array is split.  For example,
148         ``[2, 3]`` would, for ``axis=0``, result in
149 
150           - ary[:2]
151           - ary[2:3]
152           - ary[3:]
153 
154         If an index exceeds the dimension of the tensor along `axis`,
155         an empty sub-tensor is returned correspondingly.
156     axis : int, optional
157         The axis along which to split, default is 0.
158 
159     Returns
160     -------
161     sub-tensors : list of Tensors
162         A list of sub-tensors.
163 
164     Raises
165     ------
166     ValueError
167         If `indices_or_sections` is given as an integer, but
168         a split does not result in equal division.
169 
170     See Also
171     --------
172     array_split : Split a tensor into multiple sub-tensors of equal or
173                   near-equal size.  Does not raise an exception if
174                   an equal division cannot be made.
175     hsplit : Split  into multiple sub-arrays horizontally (column-wise).
176     vsplit : Split tensor into multiple sub-tensors vertically (row wise).
177     dsplit : Split tensor into multiple sub-tensors along the 3rd axis (depth).
178     concatenate : Join a sequence of tensors along an existing axis.
179     stack : Join a sequence of tensors along a new axis.
180     hstack : Stack tensors in sequence horizontally (column wise).
181     vstack : Stack tensors in sequence vertically (row wise).
182     dstack : Stack tensors in sequence depth wise (along third dimension).
183 
184     Examples
185     --------
186     >>> import mars.tensor as mt
187 
188     >>> x = mt.arange(9.0)
189     >>> mt.split(x, 3).execute()
190     [array([ 0.,  1.,  2.]), array([ 3.,  4.,  5.]), array([ 6.,  7.,  8.])]
191 
192     >>> x = mt.arange(8.0)
193     >>> mt.split(x, [3, 5, 6, 10]).execute()
194     [array([ 0.,  1.,  2.]),
195      array([ 3.,  4.]),
196      array([ 5.]),
197      array([ 6.,  7.]),
198      array([], dtype=float64)]
199 
200     """
201     return _split(ary, indices_or_sections, axis=axis, is_split=True)
202
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mars/tensor/base/split.py b/mars/tensor/base/split.py
--- a/mars/tensor/base/split.py
+++ b/mars/tensor/base/split.py
@@ -21,6 +21,7 @@
 from ...lib.sparse.core import get_array_module
 from ...core import ExecutableTuple
 from ..core import Tensor
+from ..datasource import tensor as astensor
 from ..utils import calc_sliced_size
 from ..operands import TensorHasInput, TensorOperandMixin
 
@@ -198,4 +199,4 @@
      array([], dtype=float64)]
 
     """
-    return _split(ary, indices_or_sections, axis=axis, is_split=True)
+    return _split(astensor(ary), indices_or_sections, axis=axis, is_split=True)

{"golden_diff": "diff --git a/mars/tensor/base/split.py b/mars/tensor/base/split.py\n--- a/mars/tensor/base/split.py\n+++ b/mars/tensor/base/split.py\n@@ -21,6 +21,7 @@\n from ...lib.sparse.core import get_array_module\n from ...core import ExecutableTuple\n from ..core import Tensor\n+from ..datasource import tensor as astensor\n from ..utils import calc_sliced_size\n from ..operands import TensorHasInput, TensorOperandMixin\n \n@@ -198,4 +199,4 @@\n      array([], dtype=float64)]\n \n     \"\"\"\n-    return _split(ary, indices_or_sections, axis=axis, is_split=True)\n+    return _split(astensor(ary), indices_or_sections, axis=axis, is_split=True)\n", "issue": "[BUG]some bugs about `mt.split`\n## Describe the bug\r\nI find `mt.split` does not work well when i try to use `mt.unique` and `mt.split` to group a sorted array.\r\n\r\nI find two bugs:\r\n- `mt.split` does not support tuple and array as the first argument. Could you consider supporting this for convenience of usage? See below:\r\n```\r\n>>> mt.split((1,1,1,2,2,3), (3,5))\r\n\r\n~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in split(ary, indices_or_sections, axis)\r\n    199 \r\n    200     \"\"\"\r\n--> 201     return _split(ary, indices_or_sections, axis=axis, is_split=True)\r\n\r\n~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in _split(a, indices_or_sections, axis, is_split)\r\n    127 \r\n    128 def _split(a, indices_or_sections, axis=0, is_split=False):\r\n--> 129     op = TensorSplit(axis=axis, dtype=a.dtype)\r\n    130     return op(a, indices_or_sections, is_split=is_split)\r\n    131 \r\n\r\nAttributeError: 'list' object has no attribute 'dtype'\r\n\r\n>>> mt.split([1,1,1,2,2,3], (3,5))\r\n\r\n~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in split(ary, indices_or_sections, axis)\r\n    199 \r\n    200     \"\"\"\r\n--> 201     return _split(ary, indices_or_sections, axis=axis, is_split=True)\r\n\r\n~/anaconda3/lib/python3.7/site-packages/mars/tensor/base/split.py in _split(a, indices_or_sections, axis, is_split)\r\n    127 \r\n    128 def _split(a, indices_or_sections, axis=0, is_split=False):\r\n--> 129     op = TensorSplit(axis=axis, dtype=a.dtype)\r\n    130     return op(a, indices_or_sections, is_split=is_split)\r\n    131 \r\n\r\nAttributeError: 'tuple' object has no attribute 'dtype'\r\n```\r\n- this one seems weird. I obtain the index from `mt.unique` with a sorted array and argument `return_index` True. When I passed the executed result of a slice of this index as the second arguments of `mt.split`, the returned sub-tensors all have nan shape and i cannot execute the sub-tensor to get the value. If i passed list, tuple or a `mt.array` with literal list, `mt.split` works well. See below for details:\r\n```\r\nIn [67]: p = (1,1,1,2,2,3)                                                                                                                                                                           \r\n\r\nIn [68]: unique, index = mt.unique(p, return_index=True)                                                                                                                                             \r\n\r\nIn [69]: index.execute()                                                                                                                                                                             \r\nOut[69]: array([0, 3, 5])\r\n\r\nIn [70]: index1 = index[1:].execute()                                                                                                                                                                \r\n\r\nIn [71]: index1                                                                                                                                                                                      \r\nOut[71]: array([3, 5])\r\n\r\nIn [72]: mt.split(mt.array(p), index1)                                                                                                                                                               \r\nOut[72]: \r\n(Tensor <op=TensorSplit, shape=(nan,), key=61fbfb5330abb901e5b56269d6fbad5f,\r\n Tensor <op=TensorSplit, shape=(nan,), key=f3a4dc180f9350bb7ac5ffcb18abd297,\r\n Tensor <op=TensorSplit, shape=(nan,), key=65fadafe692317ee6ba59630753cafb5)\r\n\r\nIn [73]: mt.split(mt.array(p), mt.array((3,5)))                                                                                                                                                      \r\nOut[73]: \r\n(Tensor <op=TensorSplit, shape=(3,), key=6f04c920a336bb8ae733b50c91da57ba,\r\n Tensor <op=TensorSplit, shape=(2,), key=11ef35d05602119da39c0924a6787245,\r\n Tensor <op=TensorSplit, shape=(1,), key=dd1c7e9460185aef0991c5cfa8e77823)\r\n```\r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 1999-2020 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\n\nfrom ... import opcodes as OperandDef\nfrom ...serialize import KeyField, AnyField, Int32Field\nfrom ...lib.sparse.core import get_array_module\nfrom ...core import ExecutableTuple\nfrom ..core import Tensor\nfrom ..utils import calc_sliced_size\nfrom ..operands import TensorHasInput, TensorOperandMixin\n\n\nclass TensorSplit(TensorHasInput, TensorOperandMixin):\n    _op_type_ = OperandDef.ARRAY_SPLIT\n\n    _input = KeyField('input')\n    _indices_or_sections = AnyField('indices_or_sections')\n    _axis = Int32Field('axis')\n\n    def __init__(self, axis=None, dtype=None, **kw):\n        super().__init__(_axis=axis, _dtype=dtype, **kw)\n\n    @property\n    def indices_or_sections(self):\n        return self._indices_or_sections\n\n    @property\n    def axis(self):\n        return getattr(self, '_axis', 0)\n\n    @property\n    def output_limit(self):\n        return float('inf')\n\n    def _set_inputs(self, inputs):\n        super()._set_inputs(inputs)\n        self._input = self._inputs[0]\n        if len(self._inputs) > 1:\n            self._indices_or_sections = self._inputs[1]\n\n    def __call__(self, a, indices_or_sections, is_split=False):\n        axis = self._axis\n        size = a.shape[axis]\n        if np.isnan(size):\n            raise ValueError('cannot split array with unknown shape, '\n                             'call `.execute()` on input tensor first')\n\n        if isinstance(indices_or_sections, Tensor) and hasattr(indices_or_sections.op, 'data') and \\\n                indices_or_sections.op.data is not None:\n            indices_or_sections = indices_or_sections.op.data\n\n        try:\n            indices_or_sections = int(indices_or_sections)\n            if is_split:\n                if size % indices_or_sections:\n                    raise ValueError('tensor split does not result in an equal division')\n                nparts = indices_or_sections\n                nsplit = (size // indices_or_sections,) * nparts\n            else:\n                nparts = indices_or_sections\n                if size % indices_or_sections == 0:\n                    nsplit = (size // indices_or_sections,) * nparts\n                else:\n                    nsplit = (size // indices_or_sections + 1,) * (size % indices_or_sections) + \\\n                             (size // indices_or_sections,) * (size - size % indices_or_sections)\n        except TypeError:\n            if isinstance(indices_or_sections, Tensor):\n                nparts = indices_or_sections.shape[0] + 1\n                nsplit = (np.nan,) * nparts\n            else:\n                ind = indices_or_sections = get_array_module(indices_or_sections).asarray(indices_or_sections)\n                if indices_or_sections.ndim != 1 or not np.issubdtype(indices_or_sections.dtype, np.integer):\n                    raise TypeError('slice indices must be integers or None')\n                nparts = indices_or_sections.shape[0] + 1\n                get = lambda i: None if i < 0 or i >= len(ind) else ind[i]\n                nsplit = [calc_sliced_size(size, slice(get(j - 1), get(j))) for j in range(nparts)]\n\n        inputs = [a]\n        if isinstance(indices_or_sections, Tensor):\n            inputs.append(indices_or_sections)\n        else:\n            self._indices_or_sections = indices_or_sections\n\n        kws = [{'i': i, 'shape': a.shape[:axis] + (nsplit[i],) + a.shape[axis + 1:], 'order': a.order}\n               for i in range(nparts)]\n        return ExecutableTuple(self.new_tensors(inputs, kws=kws, output_limit=nparts))\n\n    @classmethod\n    def tile(cls, op):\n        in_tensor = op.input\n        splits = op.outputs\n        axis = op.axis\n\n        if any(np.isnan(s.shape[axis]) for s in splits):\n            # TODO(xuye.qin): when iterative tiling is ready and we can retrieve data from context,\n            # this function would be available\n            raise ValueError(f'Tensor chunk sizes are unknown: {splits}')\n\n        acc_shapes = np.cumsum([s.shape[axis] for s in splits])\n        out_kws = [dict() for _ in splits]\n        for i, split in enumerate(splits):\n            slc = slice(0 if i == 0 else acc_shapes[i - 1], acc_shapes[i])\n            new_s = in_tensor[(slice(None),) * axis + (slc,)]._inplace_tile()\n            out_kws[i]['chunks'] = new_s.chunks\n            out_kws[i]['nsplits'] = new_s.nsplits\n            out_kws[i]['shape'] = split.shape\n            out_kws[i]['order'] = op.outputs[i].order\n\n        new_op = op.copy()\n        return new_op.new_tensors(op.inputs, kws=out_kws, output_limit=len(out_kws))\n\n\ndef _split(a, indices_or_sections, axis=0, is_split=False):\n    op = TensorSplit(axis=axis, dtype=a.dtype)\n    return op(a, indices_or_sections, is_split=is_split)\n\n\ndef split(ary, indices_or_sections, axis=0):\n    \"\"\"\n    Split a tensor into multiple sub-tensors.\n\n    Parameters\n    ----------\n    ary : Tensor\n        Tensor to be divided into sub-tensors.\n    indices_or_sections : int or 1-D tensor\n        If `indices_or_sections` is an integer, N, the array will be divided\n        into N equal tensors along `axis`.  If such a split is not possible,\n        an error is raised.\n\n        If `indices_or_sections` is a 1-D tensor of sorted integers, the entries\n        indicate where along `axis` the array is split.  For example,\n        ``[2, 3]`` would, for ``axis=0``, result in\n\n          - ary[:2]\n          - ary[2:3]\n          - ary[3:]\n\n        If an index exceeds the dimension of the tensor along `axis`,\n        an empty sub-tensor is returned correspondingly.\n    axis : int, optional\n        The axis along which to split, default is 0.\n\n    Returns\n    -------\n    sub-tensors : list of Tensors\n        A list of sub-tensors.\n\n    Raises\n    ------\n    ValueError\n        If `indices_or_sections` is given as an integer, but\n        a split does not result in equal division.\n\n    See Also\n    --------\n    array_split : Split a tensor into multiple sub-tensors of equal or\n                  near-equal size.  Does not raise an exception if\n                  an equal division cannot be made.\n    hsplit : Split  into multiple sub-arrays horizontally (column-wise).\n    vsplit : Split tensor into multiple sub-tensors vertically (row wise).\n    dsplit : Split tensor into multiple sub-tensors along the 3rd axis (depth).\n    concatenate : Join a sequence of tensors along an existing axis.\n    stack : Join a sequence of tensors along a new axis.\n    hstack : Stack tensors in sequence horizontally (column wise).\n    vstack : Stack tensors in sequence vertically (row wise).\n    dstack : Stack tensors in sequence depth wise (along third dimension).\n\n    Examples\n    --------\n    >>> import mars.tensor as mt\n\n    >>> x = mt.arange(9.0)\n    >>> mt.split(x, 3).execute()\n    [array([ 0.,  1.,  2.]), array([ 3.,  4.,  5.]), array([ 6.,  7.,  8.])]\n\n    >>> x = mt.arange(8.0)\n    >>> mt.split(x, [3, 5, 6, 10]).execute()\n    [array([ 0.,  1.,  2.]),\n     array([ 3.,  4.]),\n     array([ 5.]),\n     array([ 6.,  7.]),\n     array([], dtype=float64)]\n\n    \"\"\"\n    return _split(ary, indices_or_sections, axis=axis, is_split=True)\n", "path": "mars/tensor/base/split.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 1999-2020 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\n\nfrom ... import opcodes as OperandDef\nfrom ...serialize import KeyField, AnyField, Int32Field\nfrom ...lib.sparse.core import get_array_module\nfrom ...core import ExecutableTuple\nfrom ..core import Tensor\nfrom ..datasource import tensor as astensor\nfrom ..utils import calc_sliced_size\nfrom ..operands import TensorHasInput, TensorOperandMixin\n\n\nclass TensorSplit(TensorHasInput, TensorOperandMixin):\n    _op_type_ = OperandDef.ARRAY_SPLIT\n\n    _input = KeyField('input')\n    _indices_or_sections = AnyField('indices_or_sections')\n    _axis = Int32Field('axis')\n\n    def __init__(self, axis=None, dtype=None, **kw):\n        super().__init__(_axis=axis, _dtype=dtype, **kw)\n\n    @property\n    def indices_or_sections(self):\n        return self._indices_or_sections\n\n    @property\n    def axis(self):\n        return getattr(self, '_axis', 0)\n\n    @property\n    def output_limit(self):\n        return float('inf')\n\n    def _set_inputs(self, inputs):\n        super()._set_inputs(inputs)\n        self._input = self._inputs[0]\n        if len(self._inputs) > 1:\n            self._indices_or_sections = self._inputs[1]\n\n    def __call__(self, a, indices_or_sections, is_split=False):\n        axis = self._axis\n        size = a.shape[axis]\n        if np.isnan(size):\n            raise ValueError('cannot split array with unknown shape, '\n                             'call `.execute()` on input tensor first')\n\n        if isinstance(indices_or_sections, Tensor) and hasattr(indices_or_sections.op, 'data') and \\\n                indices_or_sections.op.data is not None:\n            indices_or_sections = indices_or_sections.op.data\n\n        try:\n            indices_or_sections = int(indices_or_sections)\n            if is_split:\n                if size % indices_or_sections:\n                    raise ValueError('tensor split does not result in an equal division')\n                nparts = indices_or_sections\n                nsplit = (size // indices_or_sections,) * nparts\n            else:\n                nparts = indices_or_sections\n                if size % indices_or_sections == 0:\n                    nsplit = (size // indices_or_sections,) * nparts\n                else:\n                    nsplit = (size // indices_or_sections + 1,) * (size % indices_or_sections) + \\\n                             (size // indices_or_sections,) * (size - size % indices_or_sections)\n        except TypeError:\n            if isinstance(indices_or_sections, Tensor):\n                nparts = indices_or_sections.shape[0] + 1\n                nsplit = (np.nan,) * nparts\n            else:\n                ind = indices_or_sections = get_array_module(indices_or_sections).asarray(indices_or_sections)\n                if indices_or_sections.ndim != 1 or not np.issubdtype(indices_or_sections.dtype, np.integer):\n                    raise TypeError('slice indices must be integers or None')\n                nparts = indices_or_sections.shape[0] + 1\n                get = lambda i: None if i < 0 or i >= len(ind) else ind[i]\n                nsplit = [calc_sliced_size(size, slice(get(j - 1), get(j))) for j in range(nparts)]\n\n        inputs = [a]\n        if isinstance(indices_or_sections, Tensor):\n            inputs.append(indices_or_sections)\n        else:\n            self._indices_or_sections = indices_or_sections\n\n        kws = [{'i': i, 'shape': a.shape[:axis] + (nsplit[i],) + a.shape[axis + 1:], 'order': a.order}\n               for i in range(nparts)]\n        return ExecutableTuple(self.new_tensors(inputs, kws=kws, output_limit=nparts))\n\n    @classmethod\n    def tile(cls, op):\n        in_tensor = op.input\n        splits = op.outputs\n        axis = op.axis\n\n        if any(np.isnan(s.shape[axis]) for s in splits):\n            # TODO(xuye.qin): when iterative tiling is ready and we can retrieve data from context,\n            # this function would be available\n            raise ValueError(f'Tensor chunk sizes are unknown: {splits}')\n\n        acc_shapes = np.cumsum([s.shape[axis] for s in splits])\n        out_kws = [dict() for _ in splits]\n        for i, split in enumerate(splits):\n            slc = slice(0 if i == 0 else acc_shapes[i - 1], acc_shapes[i])\n            new_s = in_tensor[(slice(None),) * axis + (slc,)]._inplace_tile()\n            out_kws[i]['chunks'] = new_s.chunks\n            out_kws[i]['nsplits'] = new_s.nsplits\n            out_kws[i]['shape'] = split.shape\n            out_kws[i]['order'] = op.outputs[i].order\n\n        new_op = op.copy()\n        return new_op.new_tensors(op.inputs, kws=out_kws, output_limit=len(out_kws))\n\n\ndef _split(a, indices_or_sections, axis=0, is_split=False):\n    op = TensorSplit(axis=axis, dtype=a.dtype)\n    return op(a, indices_or_sections, is_split=is_split)\n\n\ndef split(ary, indices_or_sections, axis=0):\n    \"\"\"\n    Split a tensor into multiple sub-tensors.\n\n    Parameters\n    ----------\n    ary : Tensor\n        Tensor to be divided into sub-tensors.\n    indices_or_sections : int or 1-D tensor\n        If `indices_or_sections` is an integer, N, the array will be divided\n        into N equal tensors along `axis`.  If such a split is not possible,\n        an error is raised.\n\n        If `indices_or_sections` is a 1-D tensor of sorted integers, the entries\n        indicate where along `axis` the array is split.  For example,\n        ``[2, 3]`` would, for ``axis=0``, result in\n\n          - ary[:2]\n          - ary[2:3]\n          - ary[3:]\n\n        If an index exceeds the dimension of the tensor along `axis`,\n        an empty sub-tensor is returned correspondingly.\n    axis : int, optional\n        The axis along which to split, default is 0.\n\n    Returns\n    -------\n    sub-tensors : list of Tensors\n        A list of sub-tensors.\n\n    Raises\n    ------\n    ValueError\n        If `indices_or_sections` is given as an integer, but\n        a split does not result in equal division.\n\n    See Also\n    --------\n    array_split : Split a tensor into multiple sub-tensors of equal or\n                  near-equal size.  Does not raise an exception if\n                  an equal division cannot be made.\n    hsplit : Split  into multiple sub-arrays horizontally (column-wise).\n    vsplit : Split tensor into multiple sub-tensors vertically (row wise).\n    dsplit : Split tensor into multiple sub-tensors along the 3rd axis (depth).\n    concatenate : Join a sequence of tensors along an existing axis.\n    stack : Join a sequence of tensors along a new axis.\n    hstack : Stack tensors in sequence horizontally (column wise).\n    vstack : Stack tensors in sequence vertically (row wise).\n    dstack : Stack tensors in sequence depth wise (along third dimension).\n\n    Examples\n    --------\n    >>> import mars.tensor as mt\n\n    >>> x = mt.arange(9.0)\n    >>> mt.split(x, 3).execute()\n    [array([ 0.,  1.,  2.]), array([ 3.,  4.,  5.]), array([ 6.,  7.,  8.])]\n\n    >>> x = mt.arange(8.0)\n    >>> mt.split(x, [3, 5, 6, 10]).execute()\n    [array([ 0.,  1.,  2.]),\n     array([ 3.,  4.]),\n     array([ 5.]),\n     array([ 6.,  7.]),\n     array([], dtype=float64)]\n\n    \"\"\"\n    return _split(astensor(ary), indices_or_sections, axis=axis, is_split=True)\n", "path": "mars/tensor/base/split.py"}]}