Repository: mars-project/mars

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)
```



Discussion:
Thank you for your report, we will reproduce the error and fix it ASAP.
I am fixing the first bug, i will issue a PR later

Resolving patch:
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 @@ def split(ary, indices_or_sections, axis=0):
      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)


Test patch:
diff --git a/mars/tensor/base/tests/test_base.py b/mars/tensor/base/tests/test_base.py
--- a/mars/tensor/base/tests/test_base.py
+++ b/mars/tensor/base/tests/test_base.py
@@ -370,6 +370,10 @@ def testSplit(self):
         self.assertTrue(splits[2].flags['F_CONTIGUOUS'])
         self.assertFalse(splits[0].flags['C_CONTIGUOUS'])
 
+        for a in ((1,1,1,2,2,3), [1,1,1,2,2,3]):
+            splits = split(a, (3,5))
+            self.assertEqual(len(splits), 3)
+
     def testSqueeze(self):
         data = np.array([[[0], [1], [2]]])
         x = tensor(data)
diff --git a/mars/tensor/base/tests/test_base_execute.py b/mars/tensor/base/tests/test_base_execute.py
--- a/mars/tensor/base/tests/test_base_execute.py
+++ b/mars/tensor/base/tests/test_base_execute.py
@@ -444,6 +444,16 @@ def testArraySplitExecution(self):
         [np.testing.assert_equal(r, e) for r, e in zip(res, expected)]
 
     def testSplitExecution(self):
+        for a in ((1,1,1,2,2,3), [1,1,1,2,2,3]):
+            splits = split(a, (3,5))
+            self.assertEqual(len(splits), 3)
+            splits0 = self.executor.execute_tensor(splits[0], concat=True)[0]
+            np.testing.assert_array_equal(splits0, (1,1,1))
+            splits1 = self.executor.execute_tensor(splits[1], concat=True)[0]
+            np.testing.assert_array_equal(splits1, (2,2))
+            splits2 = self.executor.execute_tensor(splits[2], concat=True)[0]
+            np.testing.assert_array_equal(splits2, (3,))
+
         x = arange(48, chunk_size=3).reshape(2, 3, 8)
         ss = split(x, 4, axis=2)