We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG][TENSOR] Chunks with same shape tiled by ones as well as zeros generate different key
<!--
Thank you for your contribution!

Please review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.
-->

**Describe the bug**

Chunks with same shape tiled by `ones` as well as `zeros` generate different keys, they should be the same.

**To Reproduce**

```
In [1]: import mars.tensor as mt                                                    

In [2]: a = mt.ones((100, 100), chunk_size=50)                                      

In [3]: a.tiles()                                                                   
Out[3]: Tensor <op=TensorOnes, shape=(100, 100), key=a4095842f813f99d58aa7cd330815190>

In [4]: [c.op.key for c in a.chunks]                                                
Out[4]: 
['1fc86c1b04351958eb2fda3ce467f5bf',
 '0c710bf1f48424bca05d12ee833a1234',
 '78900ebd5fa9c9baeafd17469eb9d757',
 '77942146d3fc310de36f12e1809dc41a']
```


--- 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/expressions/datasource/core.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # Copyright 1999-2018 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 itertools
18 
19 import numpy as np
20 
21 from .... import opcodes as OperandDef
22 from ....operands import DataSource
23 from ....compat import izip
24 from ....config import options
25 from ....serialize import StringField
26 from ....utils import to_str
27 from ..utils import normalize_shape, decide_chunk_sizes
28 from ..core import TensorOperandMixin
29 
30 
31 class TensorDataSource(DataSource, TensorOperandMixin):
32     """
33     Tensor data source base class, provide universal tile logic,
34     subclass can overwrite tile method.
35     """
36 
37     __slots__ = ()
38 
39     def to_chunk_op(self, *args):
40         chunk_shape, idx, chunk_size = args
41         chunk_op = self.copy().reset_key()
42         chunk_op.params = {'size': chunk_shape, 'index': idx}  # to make op key different
43         return chunk_op
44 
45     @classmethod
46     def tile(cls, op):
47         tensor = op.outputs[0]
48 
49         chunk_size = tensor.params.raw_chunk_size or options.tensor.chunk_size
50         chunk_size = decide_chunk_sizes(tensor.shape, chunk_size, tensor.dtype.itemsize)
51         chunk_size_idxes = (range(len(size)) for size in chunk_size)
52 
53         out_chunks = []
54         for chunk_shape, chunk_idx in izip(itertools.product(*chunk_size),
55                                            itertools.product(*chunk_size_idxes)):
56             chunk_op = op.to_chunk_op(chunk_shape, chunk_idx, chunk_size)
57             out_chunk = chunk_op.new_chunk(None, chunk_shape, index=chunk_idx)
58             out_chunks.append(out_chunk)
59 
60         new_op = op.copy()
61         return new_op.new_tensors(op.inputs, tensor.shape, chunks=out_chunks, nsplits=chunk_size)
62 
63 
64 class TensorNoInput(TensorDataSource):
65     """
66     Tensor operand with no inputs.
67     """
68 
69     def check_inputs(self, inputs):
70         # no inputs
71         if inputs and len(inputs) > 0:
72             raise ValueError("Tensor data source has no inputs")
73 
74     def calc_shape(self, *inputs_shape):
75         return self.outputs[0].shape
76 
77     def _new_chunks(self, inputs, shape, index=None, output_limit=None, kws=None, **kw):
78         self.params['shape'] = shape  # set shape to make the operand key different
79         return super(TensorNoInput, self)._new_chunks(
80             inputs, shape, index=index, output_limit=output_limit, kws=kws, **kw)
81 
82     def _new_entities(self, inputs, shape, chunks=None, nsplits=None, output_limit=None,
83                       kws=None, **kw):
84         self.params['shape'] = shape  # set shape to make the operand key different
85         return super(TensorNoInput, self)._new_entities(
86             inputs, shape, chunks=chunks, nsplits=nsplits, output_limit=output_limit,
87             kws=kws, **kw)
88 
89     def __call__(self, shape, chunk_size=None):
90         shape = normalize_shape(shape)
91         return self.new_tensor(None, shape, raw_chunk_size=chunk_size)
92 
93 
94 class TensorHasInput(TensorDataSource):
95     """
96     Tensor operand with a single input.
97     """
98 
99     @property
100     def input(self):
101         return self._input
102 
103     def check_inputs(self, inputs):
104         # no inputs
105         if len(inputs) != 1:
106             raise ValueError("Tensor can only have 1 input")
107 
108     def _set_inputs(self, inputs):
109         super(TensorHasInput, self)._set_inputs(inputs)
110         self._input = self._inputs[0]
111 
112     @classmethod
113     def tile(cls, op):
114         out_chunks = []
115         for c in op.input.chunks:
116             out_chunk = op.copy().reset_key().new_chunk([c], c.shape, index=c.index)
117             out_chunks.append(out_chunk)
118 
119         new_op = op.copy()
120         return new_op.new_tensors(op.inputs, op.outputs[0].shape, chunks=out_chunks,
121                                   nsplits=op.input.nsplits)
122 
123     def calc_shape(self, *inputs_shape):
124         return inputs_shape[0]
125 
126     def __call__(self, a):
127         return self.new_tensor([a], a.shape)
128 
129 
130 class TensorLike(TensorHasInput):
131     def _set_inputs(self, inputs):
132         super(TensorLike, self)._set_inputs(inputs)
133         if self.dtype is None:
134             self._dtype = self.input.dtype
135         if self.gpu is None:
136             self._gpu = self.input.op.gpu
137 
138         # FIXME: remove when cupy supports other dtypes
139         if self._gpu and self._dtype not in (np.float32, np.float64):
140             raise NotImplementedError('Sparse tensor on GPU only supports float32 and float64')
141 
142 
143 class TensorFetch(TensorNoInput):
144     _op_type_ = OperandDef.FETCH
145 
146     _to_fetch_key = StringField('to_fetch_key', on_serialize=to_str)
147 
148     def __init__(self, dtype=None, to_fetch_key=None, **kw):
149         super(TensorFetch, self).__init__(
150             _dtype=dtype, _to_fetch_key=to_fetch_key, **kw)
151 
152     def _new_chunks(self, inputs, shape, index=None, output_limit=None, kws=None, **kw):
153         if '_key' in kw and self._to_fetch_key is None:
154             self._to_fetch_key = kw['_key']
155         return super(TensorFetch, self)._new_chunks(
156             inputs, shape, index=index, output_limit=output_limit, kws=kws, **kw)
157 
158     def _new_entities(self, inputs, shape, chunks=None, nsplits=None, output_limit=None,
159                       kws=None, **kw):
160         if '_key' in kw and self._to_fetch_key is None:
161             self._to_fetch_key = kw['_key']
162         return super(TensorFetch, self)._new_entities(
163             inputs, shape, chunks=chunks, nsplits=nsplits,
164             output_limit=output_limit, kws=kws, **kw)
165 
166     @classmethod
167     def tile(cls, op):
168         raise NotImplementedError('Fetch tile cannot be handled by operand itself')
169
```
--- 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/expressions/datasource/core.py b/mars/tensor/expressions/datasource/core.py
--- a/mars/tensor/expressions/datasource/core.py
+++ b/mars/tensor/expressions/datasource/core.py
@@ -37,9 +37,9 @@
     __slots__ = ()
 
     def to_chunk_op(self, *args):
-        chunk_shape, idx, chunk_size = args
+        chunk_shape, _, chunk_size = args
         chunk_op = self.copy().reset_key()
-        chunk_op.params = {'size': chunk_shape, 'index': idx}  # to make op key different
+        chunk_op.params = {'size': chunk_shape}  # to make op key different
         return chunk_op
 
     @classmethod

{"golden_diff": "diff --git a/mars/tensor/expressions/datasource/core.py b/mars/tensor/expressions/datasource/core.py\n--- a/mars/tensor/expressions/datasource/core.py\n+++ b/mars/tensor/expressions/datasource/core.py\n@@ -37,9 +37,9 @@\n     __slots__ = ()\n \n     def to_chunk_op(self, *args):\n-        chunk_shape, idx, chunk_size = args\n+        chunk_shape, _, chunk_size = args\n         chunk_op = self.copy().reset_key()\n-        chunk_op.params = {'size': chunk_shape, 'index': idx}  # to make op key different\n+        chunk_op.params = {'size': chunk_shape}  # to make op key different\n         return chunk_op\n \n     @classmethod\n", "issue": "[BUG][TENSOR] Chunks with same shape tiled by ones as well as zeros generate different key\n<!--\r\nThank you for your contribution!\r\n\r\nPlease review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.\r\n-->\r\n\r\n**Describe the bug**\r\n\r\nChunks with same shape tiled by `ones` as well as `zeros` generate different keys, they should be the same.\r\n\r\n**To Reproduce**\r\n\r\n```\r\nIn [1]: import mars.tensor as mt                                                    \r\n\r\nIn [2]: a = mt.ones((100, 100), chunk_size=50)                                      \r\n\r\nIn [3]: a.tiles()                                                                   \r\nOut[3]: Tensor <op=TensorOnes, shape=(100, 100), key=a4095842f813f99d58aa7cd330815190>\r\n\r\nIn [4]: [c.op.key for c in a.chunks]                                                \r\nOut[4]: \r\n['1fc86c1b04351958eb2fda3ce467f5bf',\r\n '0c710bf1f48424bca05d12ee833a1234',\r\n '78900ebd5fa9c9baeafd17469eb9d757',\r\n '77942146d3fc310de36f12e1809dc41a']\r\n```\r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 1999-2018 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 itertools\n\nimport numpy as np\n\nfrom .... import opcodes as OperandDef\nfrom ....operands import DataSource\nfrom ....compat import izip\nfrom ....config import options\nfrom ....serialize import StringField\nfrom ....utils import to_str\nfrom ..utils import normalize_shape, decide_chunk_sizes\nfrom ..core import TensorOperandMixin\n\n\nclass TensorDataSource(DataSource, TensorOperandMixin):\n    \"\"\"\n    Tensor data source base class, provide universal tile logic,\n    subclass can overwrite tile method.\n    \"\"\"\n\n    __slots__ = ()\n\n    def to_chunk_op(self, *args):\n        chunk_shape, idx, chunk_size = args\n        chunk_op = self.copy().reset_key()\n        chunk_op.params = {'size': chunk_shape, 'index': idx}  # to make op key different\n        return chunk_op\n\n    @classmethod\n    def tile(cls, op):\n        tensor = op.outputs[0]\n\n        chunk_size = tensor.params.raw_chunk_size or options.tensor.chunk_size\n        chunk_size = decide_chunk_sizes(tensor.shape, chunk_size, tensor.dtype.itemsize)\n        chunk_size_idxes = (range(len(size)) for size in chunk_size)\n\n        out_chunks = []\n        for chunk_shape, chunk_idx in izip(itertools.product(*chunk_size),\n                                           itertools.product(*chunk_size_idxes)):\n            chunk_op = op.to_chunk_op(chunk_shape, chunk_idx, chunk_size)\n            out_chunk = chunk_op.new_chunk(None, chunk_shape, index=chunk_idx)\n            out_chunks.append(out_chunk)\n\n        new_op = op.copy()\n        return new_op.new_tensors(op.inputs, tensor.shape, chunks=out_chunks, nsplits=chunk_size)\n\n\nclass TensorNoInput(TensorDataSource):\n    \"\"\"\n    Tensor operand with no inputs.\n    \"\"\"\n\n    def check_inputs(self, inputs):\n        # no inputs\n        if inputs and len(inputs) > 0:\n            raise ValueError(\"Tensor data source has no inputs\")\n\n    def calc_shape(self, *inputs_shape):\n        return self.outputs[0].shape\n\n    def _new_chunks(self, inputs, shape, index=None, output_limit=None, kws=None, **kw):\n        self.params['shape'] = shape  # set shape to make the operand key different\n        return super(TensorNoInput, self)._new_chunks(\n            inputs, shape, index=index, output_limit=output_limit, kws=kws, **kw)\n\n    def _new_entities(self, inputs, shape, chunks=None, nsplits=None, output_limit=None,\n                      kws=None, **kw):\n        self.params['shape'] = shape  # set shape to make the operand key different\n        return super(TensorNoInput, self)._new_entities(\n            inputs, shape, chunks=chunks, nsplits=nsplits, output_limit=output_limit,\n            kws=kws, **kw)\n\n    def __call__(self, shape, chunk_size=None):\n        shape = normalize_shape(shape)\n        return self.new_tensor(None, shape, raw_chunk_size=chunk_size)\n\n\nclass TensorHasInput(TensorDataSource):\n    \"\"\"\n    Tensor operand with a single input.\n    \"\"\"\n\n    @property\n    def input(self):\n        return self._input\n\n    def check_inputs(self, inputs):\n        # no inputs\n        if len(inputs) != 1:\n            raise ValueError(\"Tensor can only have 1 input\")\n\n    def _set_inputs(self, inputs):\n        super(TensorHasInput, self)._set_inputs(inputs)\n        self._input = self._inputs[0]\n\n    @classmethod\n    def tile(cls, op):\n        out_chunks = []\n        for c in op.input.chunks:\n            out_chunk = op.copy().reset_key().new_chunk([c], c.shape, index=c.index)\n            out_chunks.append(out_chunk)\n\n        new_op = op.copy()\n        return new_op.new_tensors(op.inputs, op.outputs[0].shape, chunks=out_chunks,\n                                  nsplits=op.input.nsplits)\n\n    def calc_shape(self, *inputs_shape):\n        return inputs_shape[0]\n\n    def __call__(self, a):\n        return self.new_tensor([a], a.shape)\n\n\nclass TensorLike(TensorHasInput):\n    def _set_inputs(self, inputs):\n        super(TensorLike, self)._set_inputs(inputs)\n        if self.dtype is None:\n            self._dtype = self.input.dtype\n        if self.gpu is None:\n            self._gpu = self.input.op.gpu\n\n        # FIXME: remove when cupy supports other dtypes\n        if self._gpu and self._dtype not in (np.float32, np.float64):\n            raise NotImplementedError('Sparse tensor on GPU only supports float32 and float64')\n\n\nclass TensorFetch(TensorNoInput):\n    _op_type_ = OperandDef.FETCH\n\n    _to_fetch_key = StringField('to_fetch_key', on_serialize=to_str)\n\n    def __init__(self, dtype=None, to_fetch_key=None, **kw):\n        super(TensorFetch, self).__init__(\n            _dtype=dtype, _to_fetch_key=to_fetch_key, **kw)\n\n    def _new_chunks(self, inputs, shape, index=None, output_limit=None, kws=None, **kw):\n        if '_key' in kw and self._to_fetch_key is None:\n            self._to_fetch_key = kw['_key']\n        return super(TensorFetch, self)._new_chunks(\n            inputs, shape, index=index, output_limit=output_limit, kws=kws, **kw)\n\n    def _new_entities(self, inputs, shape, chunks=None, nsplits=None, output_limit=None,\n                      kws=None, **kw):\n        if '_key' in kw and self._to_fetch_key is None:\n            self._to_fetch_key = kw['_key']\n        return super(TensorFetch, self)._new_entities(\n            inputs, shape, chunks=chunks, nsplits=nsplits,\n            output_limit=output_limit, kws=kws, **kw)\n\n    @classmethod\n    def tile(cls, op):\n        raise NotImplementedError('Fetch tile cannot be handled by operand itself')\n", "path": "mars/tensor/expressions/datasource/core.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 1999-2018 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 itertools\n\nimport numpy as np\n\nfrom .... import opcodes as OperandDef\nfrom ....operands import DataSource\nfrom ....compat import izip\nfrom ....config import options\nfrom ....serialize import StringField\nfrom ....utils import to_str\nfrom ..utils import normalize_shape, decide_chunk_sizes\nfrom ..core import TensorOperandMixin\n\n\nclass TensorDataSource(DataSource, TensorOperandMixin):\n    \"\"\"\n    Tensor data source base class, provide universal tile logic,\n    subclass can overwrite tile method.\n    \"\"\"\n\n    __slots__ = ()\n\n    def to_chunk_op(self, *args):\n        chunk_shape, _, chunk_size = args\n        chunk_op = self.copy().reset_key()\n        chunk_op.params = {'size': chunk_shape}  # to make op key different\n        return chunk_op\n\n    @classmethod\n    def tile(cls, op):\n        tensor = op.outputs[0]\n\n        chunk_size = tensor.params.raw_chunk_size or options.tensor.chunk_size\n        chunk_size = decide_chunk_sizes(tensor.shape, chunk_size, tensor.dtype.itemsize)\n        chunk_size_idxes = (range(len(size)) for size in chunk_size)\n\n        out_chunks = []\n        for chunk_shape, chunk_idx in izip(itertools.product(*chunk_size),\n                                           itertools.product(*chunk_size_idxes)):\n            chunk_op = op.to_chunk_op(chunk_shape, chunk_idx, chunk_size)\n            out_chunk = chunk_op.new_chunk(None, chunk_shape, index=chunk_idx)\n            out_chunks.append(out_chunk)\n\n        new_op = op.copy()\n        return new_op.new_tensors(op.inputs, tensor.shape, chunks=out_chunks, nsplits=chunk_size)\n\n\nclass TensorNoInput(TensorDataSource):\n    \"\"\"\n    Tensor operand with no inputs.\n    \"\"\"\n\n    def check_inputs(self, inputs):\n        # no inputs\n        if inputs and len(inputs) > 0:\n            raise ValueError(\"Tensor data source has no inputs\")\n\n    def calc_shape(self, *inputs_shape):\n        return self.outputs[0].shape\n\n    def _new_chunks(self, inputs, shape, index=None, output_limit=None, kws=None, **kw):\n        self.params['shape'] = shape  # set shape to make the operand key different\n        return super(TensorNoInput, self)._new_chunks(\n            inputs, shape, index=index, output_limit=output_limit, kws=kws, **kw)\n\n    def _new_entities(self, inputs, shape, chunks=None, nsplits=None, output_limit=None,\n                      kws=None, **kw):\n        self.params['shape'] = shape  # set shape to make the operand key different\n        return super(TensorNoInput, self)._new_entities(\n            inputs, shape, chunks=chunks, nsplits=nsplits, output_limit=output_limit,\n            kws=kws, **kw)\n\n    def __call__(self, shape, chunk_size=None):\n        shape = normalize_shape(shape)\n        return self.new_tensor(None, shape, raw_chunk_size=chunk_size)\n\n\nclass TensorHasInput(TensorDataSource):\n    \"\"\"\n    Tensor operand with a single input.\n    \"\"\"\n\n    @property\n    def input(self):\n        return self._input\n\n    def check_inputs(self, inputs):\n        # no inputs\n        if len(inputs) != 1:\n            raise ValueError(\"Tensor can only have 1 input\")\n\n    def _set_inputs(self, inputs):\n        super(TensorHasInput, self)._set_inputs(inputs)\n        self._input = self._inputs[0]\n\n    @classmethod\n    def tile(cls, op):\n        out_chunks = []\n        for c in op.input.chunks:\n            out_chunk = op.copy().reset_key().new_chunk([c], c.shape, index=c.index)\n            out_chunks.append(out_chunk)\n\n        new_op = op.copy()\n        return new_op.new_tensors(op.inputs, op.outputs[0].shape, chunks=out_chunks,\n                                  nsplits=op.input.nsplits)\n\n    def calc_shape(self, *inputs_shape):\n        return inputs_shape[0]\n\n    def __call__(self, a):\n        return self.new_tensor([a], a.shape)\n\n\nclass TensorLike(TensorHasInput):\n    def _set_inputs(self, inputs):\n        super(TensorLike, self)._set_inputs(inputs)\n        if self.dtype is None:\n            self._dtype = self.input.dtype\n        if self.gpu is None:\n            self._gpu = self.input.op.gpu\n\n        # FIXME: remove when cupy supports other dtypes\n        if self._gpu and self._dtype not in (np.float32, np.float64):\n            raise NotImplementedError('Sparse tensor on GPU only supports float32 and float64')\n\n\nclass TensorFetch(TensorNoInput):\n    _op_type_ = OperandDef.FETCH\n\n    _to_fetch_key = StringField('to_fetch_key', on_serialize=to_str)\n\n    def __init__(self, dtype=None, to_fetch_key=None, **kw):\n        super(TensorFetch, self).__init__(\n            _dtype=dtype, _to_fetch_key=to_fetch_key, **kw)\n\n    def _new_chunks(self, inputs, shape, index=None, output_limit=None, kws=None, **kw):\n        if '_key' in kw and self._to_fetch_key is None:\n            self._to_fetch_key = kw['_key']\n        return super(TensorFetch, self)._new_chunks(\n            inputs, shape, index=index, output_limit=output_limit, kws=kws, **kw)\n\n    def _new_entities(self, inputs, shape, chunks=None, nsplits=None, output_limit=None,\n                      kws=None, **kw):\n        if '_key' in kw and self._to_fetch_key is None:\n            self._to_fetch_key = kw['_key']\n        return super(TensorFetch, self)._new_entities(\n            inputs, shape, chunks=chunks, nsplits=nsplits,\n            output_limit=output_limit, kws=kws, **kw)\n\n    @classmethod\n    def tile(cls, op):\n        raise NotImplementedError('Fetch tile cannot be handled by operand itself')\n", "path": "mars/tensor/expressions/datasource/core.py"}]}