# Buggy code
def _partial_reduction(
    cls, agg_op_type, tensor, axis, dtype, keepdims, combine_size, kw=None
):
    from ..merge.concatenate import TensorConcatenate

    kw = kw or {}
    axes = sorted(combine_size.keys())

    combine_blocks = [
        cls._combine_split(i, combine_size, tensor.chunk_shape)
        for i in range(tensor.ndim)
    ]
    combine_blocks_idxes = [range(len(blocks)) for blocks in combine_blocks]

    chunks = []
    for combine_block_idx, combine_block in izip(
        itertools.product(*combine_blocks_idxes), itertools.product(*combine_blocks)
    ):
        chks = [tensor.cix[idx] for idx in itertools.product(*combine_block)]
        op = TensorConcatenate(axis=axes, dtype=chks[0].dtype)
        chk = op.new_chunk(chks, shape=cls._concatenate_shape(tensor, combine_block))
        shape = tuple(
            s if i not in combine_size else 1
            for i, s in enumerate(chk.shape)
            if keepdims or i not in combine_size
        )
        agg_op = agg_op_type(axis=axis, dtype=dtype, keepdims=keepdims, **kw)
        chunk = agg_op.new_chunk(
            [chk],
            shape=shape,
            index=tuple(
                idx
                for i, idx in enumerate(combine_block_idx)
                if keepdims or i not in combine_size
            ),
        )
        chunks.append(chunk)

    nsplits = [
        tuple(
            c.shape[i]
            for c in chunks
            if builtins.all(idx == 0 for j, idx in enumerate(c.index) if j != i)
        )
        for i in range(len(chunks[0].shape))
    ]
    shape = tuple(builtins.sum(nsplit) for nsplit in nsplits)
    agg_op = agg_op_type(
        axis=axis, dtype=dtype, keepdims=keepdims, combine_size=combine_size, **kw
    )
    return agg_op.new_tensors([tensor], shape, chunks=chunks, nsplits=nsplits)


# Traceback (IndexError)
In [1]: import mars.tensor as mt

In [2]: a = mt.arange(12)

In [3]: a.totiledb('test_tiledb').execute()
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-3-5174935f197d> in <module>
----> 1 a.totiledb('test_tiledb').execute()

~/Documents/mars_dev/mars/mars/tensor/core.py in execute(self, session, **kw)
378
379     def execute(self, session=None, **kw):
--> 380         return self._data.execute(session, **kw)
381
382

~/Documents/mars_dev/mars/mars/tensor/core.py in execute(self, session, **kw)
168         if session is None:
169             session = Session.default_or_local()
--> 170         return session.run(self, **kw)
171
172     def fetch(self, session=None, **kw):

~/Documents/mars_dev/mars/mars/session.py in run(self, *tensors, **kw)
107
108         tensors = tuple(mt.tensor(t) for t in tensors)
--> 109         result = self._sess.run(*tensors, **kw)
110
111         for t in tensors:

~/Documents/mars_dev/mars/mars/session.py in run(self, *tensors, **kw)
49         if 'n_parallel' not in kw:
50             kw['n_parallel'] = cpu_count()
---> 51         res = self._executor.execute_tensors(tensors, **kw)
52         return res
53

~/Documents/mars_dev/mars/mars/utils.py in _wrapped(*args, **kwargs)
350         try:
351             _kernel_mode.eager = False
--> 352             return func(*args, **kwargs)
353         finally:
354             _kernel_mode.eager = None

~/Documents/mars_dev/mars/mars/executor.py in execute_tensors(self, tensors, fetch, n_parallel, n_thread, print_progress, mock, compose)
530
531         self.execute_graph(graph, result_keys, n_parallel=n_parallel or n_thread,
--> 532                            print_progress=print_progress, mock=mock)
533
534         results = self._chunk_result

~/Documents/mars_dev/mars/mars/executor.py in execute_graph(self, graph, keys, n_parallel, print_progress, mock, retval)
464                                          print_progress=print_progress, mock=mock,
465                                          mock_max_memory=self._mock_max_memory)
--> 466         res = graph_execution.execute(retval)
467         self._mock_max_memory = max(self._mock_max_memory, graph_execution._mock_max_memory)
468         if mock:

~/Documents/mars_dev/mars/mars/executor.py in execute(self, retval)
377         # wait until all the futures completed
378         for future in executed_futures:
--> 379             future.result()
380
381         # update with the maximal memory cost during the whole execution

~/miniconda3/lib/python3.7/concurrent/futures/_base.py in result(self, timeout)
430                 raise CancelledError()
431             elif self._state == FINISHED:
--> 432                 return self.__get_result()
433             else:
434                 raise TimeoutError()

~/miniconda3/lib/python3.7/concurrent/futures/_base.py in __get_result(self)
382     def __get_result(self):
383         if self._exception:
--> 384             raise self._exception
385         else:
386             return self._result

~/miniconda3/lib/python3.7/concurrent/futures/thread.py in run(self)
55
56         try:
---> 57             result = self.fn(*self.args, **self.kwargs)
58         except BaseException as exc:
59             self.future.set_exception(exc)

~/Documents/mars_dev/mars/mars/executor.py in _execute_operand(self, op)
260             # so we pass the first operand's first output to Executor.handle
261             first_op = ops[0]
--> 262             Executor.handle(first_op.outputs[0], results, self._mock)
263
264             # update maximal memory usage during execution

~/Documents/mars_dev/mars/mars/executor.py in handle(cls, chunk, results, mock)
450     def handle(cls, chunk, results, mock=False):
451         if not mock:
--> 452             return cls._get_op_runner(chunk, cls._op_runners)(results, chunk)
453         else:
454             return cls._get_op_runner(chunk, cls._op_size_estimators)(results, chunk)

~/Documents/mars_dev/mars/mars/tensor/execution/datastore.py in _store_tiledb(ctx, chunk)
44         with tiledb.DenseArray(uri=uri, ctx=tiledb_ctx, mode='w',
45                                key=key, timestamp=timestamp) as arr:
---> 46             arr[tuple(slcs)] = to_store
47         ctx[chunk.key] = np.empty((0,) * chunk.ndim, dtype=chunk.dtype)
48     else:

tiledb/libtiledb.pyx in tiledb.libtiledb.DenseArray.__setitem__()

tiledb/libtiledb.pyx in tiledb.libtiledb.index_domain_subarray()

IndexError: too many indices for array

# Fixed code
def _partial_reduction(
    cls, agg_op_type, tensor, axis, dtype, keepdims, combine_size, kw=None
):
    from ..merge.concatenate import TensorConcatenate

    kw = kw or {}
    axes = sorted(combine_size.keys())

    combine_blocks = [
        cls._combine_split(i, combine_size, tensor.chunk_shape)
        for i in range(tensor.ndim)
    ]
    combine_blocks_idxes = [range(len(blocks)) for blocks in combine_blocks]

    chunks = []
    for combine_block_idx, combine_block in izip(
        itertools.product(*combine_blocks_idxes), itertools.product(*combine_blocks)
    ):
        chks = [tensor.cix[idx] for idx in itertools.product(*combine_block)]
        if len(chks) > 1:
            op = TensorConcatenate(axis=axes, dtype=chks[0].dtype)
            chk = op.new_chunk(
                chks, shape=cls._concatenate_shape(tensor, combine_block)
            )
        else:
            chk = chks[0]
        shape = tuple(
            s if i not in combine_size else 1
            for i, s in enumerate(chk.shape)
            if keepdims or i not in combine_size
        )
        agg_op = agg_op_type(axis=axis, dtype=dtype, keepdims=keepdims, **kw)
        chunk = agg_op.new_chunk(
            [chk],
            shape=shape,
            index=tuple(
                idx
                for i, idx in enumerate(combine_block_idx)
                if keepdims or i not in combine_size
            ),
        )
        chunks.append(chunk)

    nsplits = [
        tuple(
            c.shape[i]
            for c in chunks
            if builtins.all(idx == 0 for j, idx in enumerate(c.index) if j != i)
        )
        for i in range(len(chunks[0].shape))
    ]
    shape = tuple(builtins.sum(nsplit) for nsplit in nsplits)
    agg_op = agg_op_type(
        axis=axis, dtype=dtype, keepdims=keepdims, combine_size=combine_size, **kw
    )
    return agg_op.new_tensors([tensor], shape, chunks=chunks, nsplits=nsplits)