# Buggy code
def _auto_concat_dataframe_chunks(chunk, inputs):
    if chunk.op.axis is not None:
        return pd.concat(inputs, axis=op.axis)
    # auto generated concat when executing a DataFrame
    n_rows = max(inp.index[0] for inp in chunk.inputs) + 1
    n_cols = int(len(inputs) // n_rows)
    assert n_rows * n_cols == len(inputs)

    xdf = pd if isinstance(inputs[0], pd.DataFrame) else cudf

    concats = []
    for i in range(n_rows):
        concat = xdf.concat([inputs[i * n_cols + j] for j in range(n_cols)], axis=1)
        concats.append(concat)

    if xdf is pd:
        # The `sort=False` is to suppress a `FutureWarning` of pandas, when the index or column of chunks to
        # concatenate is not aligned, which may happens for certain ops.
        #
        # See also Note [Columns of Left Join] in test_merge_execution.py.
        ret = xdf.concat(concats, sort=False)
    else:
        ret = xdf.concat(concats)
    if getattr(chunk.index_value, "should_be_monotonic", False):
        ret.sort_index(inplace=True)
    if getattr(chunk.columns_value, "should_be_monotonic", False):
        ret.sort_index(axis=1, inplace=True)
    return ret


# Traceback (RuntimeError)
In [5]: df = md.read_csv('/home/xuye.qin/kaisheng.hks/G1_1e8_1e2_0_0.csv', gpu=True)

In [6]: _ = df.execute()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-6-bdc0e119412a> in <module>
----> 1 _ = df.execute()

~/kaisheng.hks/mars/mars/core.py in execute(self, session, **kw)
443         if session is None:
444             session = Session.default_or_local()
--> 445         return session.run(self, **kw)
446
447     def fetch(self, session=None, **kw):

~/kaisheng.hks/mars/mars/session.py in run(self, *tileables, **kw)
179         tileables = tuple(mt.tensor(t) if not isinstance(t, (Entity, Base)) else t
180                           for t in tileables)
--> 181         result = self._sess.run(*tileables, **kw)
182
183         for t in tileables:

~/kaisheng.hks/mars/mars/session.py in run(self, *tileables, **kw)
88             # set number of running cores
89             self.context.set_ncores(kw['n_parallel'])
---> 90             res = self._executor.execute_tileables(tileables, **kw)
91             return res
92

~/kaisheng.hks/mars/mars/utils.py in _wrapped(*args, **kwargs)
384                 _kernel_mode.eager = False
385             _kernel_mode.eager_count = enter_eager_count + 1
--> 386             return func(*args, **kwargs)
387         finally:
388             _kernel_mode.eager_count -= 1

~/kaisheng.hks/mars/mars/utils.py in inner(*args, **kwargs)
471     def inner(*args, **kwargs):
472         with build_mode():
--> 473             return func(*args, **kwargs)
474     return inner
475

~/kaisheng.hks/mars/mars/executor.py in execute_tileables(self, tileables, fetch, n_parallel, n_thread, print_progress, mock, compose)
734             self.execute_graph(chunk_graph, list(temp_result_keys), n_parallel=n_parallel or n_thread,
735                                print_progress=print_progress, mock=mock,
--> 736                                chunk_result=chunk_result)
737             if chunk_graph_builder.done:
738                 if len(intermediate_result_keys) > 0:

~/kaisheng.hks/mars/mars/executor.py in execute_graph(self, graph, keys, n_parallel, print_progress, mock, no_intermediate, compose, retval, chunk_result)
610                                          mock=mock, mock_max_memory=self._mock_max_memory,
611                                          fetch_keys=fetch_keys, no_intermediate=no_intermediate)
--> 612         res = graph_execution.execute(retval)
613         self._mock_max_memory = max(self._mock_max_memory, graph_execution._mock_max_memory)
614         if mock:

~/kaisheng.hks/mars/mars/executor.py in execute(self, retval)
495         # wait until all the futures completed
496         for future in executed_futures:
--> 497             future.result()
498
499         if retval:

~/miniconda3/lib/python3.7/concurrent/futures/_base.py in result(self, timeout)
423                 raise CancelledError()
424             elif self._state == FINISHED:
--> 425                 return self.__get_result()
426
427             self._condition.wait(timeout)

~/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)

~/kaisheng.hks/mars/mars/executor.py in _execute_operand(self, op)
372             # so we pass the first operand's first output to Executor.handle
373             first_op = ops[0]
--> 374             Executor.handle(first_op, results, self._mock)
375
376             # update maximal memory usage during execution

~/kaisheng.hks/mars/mars/executor.py in handle(cls, op, results, mock)
559         try:
560             if UFuncTypeError is None:
--> 561                 return runner(results, op)
562             else:
563                 # Cast `UFuncTypeError` to `TypeError` since subclasses of the former is unpickleable.

~/kaisheng.hks/mars/mars/dataframe/datasource/read_csv.py in execute(cls, ctx, op)
209                         csv_kwargs['skiprows'] = 1 if op.header == 'infer' else op.header
210                     df = xdf.read_csv(b, sep=op.sep, names=op.names, index_col=op.index_col,
--> 211                                       dtype=out_df.dtypes.to_dict(), **csv_kwargs)
212         ctx[out_df.key] = df
213

~/miniconda3/lib/python3.7/site-packages/cudf/io/csv.py in read_csv(filepath_or_buffer, lineterminator, quotechar, quoting, doublequote, header, mangle_dupe_cols, usecols, sep, delimiter, delim_whitespace, skipinitialspace, names, dtype, skipfooter, skiprows, dayfirst, compression, thousands, decimal, true_values, false_values, nrows, byte_range, skip_blank_lines, parse_dates, comment, na_values, keep_default_na, na_filter, prefix, index_col)
79         na_filter=na_filter,
80         prefix=prefix,
---> 81         index_col=index_col,
82     )
83

cudf/bindings/csv.pyx in cudf.bindings.csv.cpp_read_csv()

cudf/bindings/csv.pyx in cudf.bindings.csv.cpp_read_csv()

RuntimeError: cuDF failure at: /conda/conda-bld/libcudf_1566414954289/work/cpp/src/io/csv/csv_reader_impl.cu:624: Unsupported data type

# Fixed code
def _auto_concat_dataframe_chunks(chunk, inputs):
    if chunk.op.axis is not None:
        return pd.concat(inputs, axis=op.axis)
    # auto generated concat when executing a DataFrame
    n_rows = max(inp.index[0] for inp in chunk.inputs) + 1
    n_cols = int(len(inputs) // n_rows)
    assert n_rows * n_cols == len(inputs)

    xdf = pd if isinstance(inputs[0], pd.DataFrame) else cudf

    concats = []
    for i in range(n_rows):
        concat = xdf.concat([inputs[i * n_cols + j] for j in range(n_cols)], axis=1)
        concats.append(concat)

    if xdf is pd:
        # The `sort=False` is to suppress a `FutureWarning` of pandas, when the index or column of chunks to
        # concatenate is not aligned, which may happens for certain ops.
        #
        # See also Note [Columns of Left Join] in test_merge_execution.py.
        ret = xdf.concat(concats, sort=False)
    else:
        ret = xdf.concat(concats)
        # cuDF will lost index name when concat two seriess.
        ret.index.name = concats[0].index.name
    if getattr(chunk.index_value, "should_be_monotonic", False):
        ret.sort_index(inplace=True)
    if getattr(chunk.columns_value, "should_be_monotonic", False):
        ret.sort_index(axis=1, inplace=True)
    return ret