【问题标题】:dask.async.MemoryError while running big data computation on EC2在 EC2 上运行大数据计算时出现 dask.async.MemoryError
【发布时间】:2016-07-18 19:42:45
【问题描述】:

我有一个 m4.4xlarge(64 GB 内存)EC2 盒子。我正在和熊猫一起跑步。我收到以下内存错误。

我在运行大约 24 小时后得到这个,这大约是完成任务所需的时间,所以我不确定错误是否是由于 RAM 不足,磁盘内存作为脚本的结尾执行 DF.to_csv() 将大 DF 写入磁盘或 pandas/numpy 内部内存限制?

raise(remote_exception(res, tb))
    dask.async.MemoryError: 

Traceback
---------
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/dask/async.py", line 267, in execute_task
    result = _execute_task(task, data)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/dask/async.py", line 248, in _execute_task
    args2 = [_execute_task(a, cache) for a in args]
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/dask/async.py", line 249, in _execute_task
    return func(*args2)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/frame.py", line 4061, in apply
    return self._apply_standard(f, axis, reduce=reduce)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/frame.py", line 4179, in _apply_standard
    result = result._convert(datetime=True, timedelta=True, copy=False)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/generic.py", line 3004, in _convert
    copy=copy)).__finalize__(self)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/internals.py", line 2941, in convert
    return self.apply('convert', **kwargs)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/internals.py", line 2901, in apply
    bm._consolidate_inplace()
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/internals.py", line 3278, in _consolidate_inplace
    self.blocks = tuple(_consolidate(self.blocks))
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/internals.py", line 4269, in _consolidate
    _can_consolidate=_can_consolidate)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/internals.py", line 4289, in _merge_blocks
    new_values = _vstack([b.values for b in blocks], dtype)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/pandas/core/internals.py", line 4335, in _vstack
    return np.vstack(to_stack)
  File "/home/ec2-user/anaconda2/lib/python2.7/site-packages/numpy/core/shape_base.py", line 230, in vstack
    return _nx.concatenate([atleast_2d(_m) for _m in tup], 0)

更新:

根据 MRocklin 的回答,提供了一些额外的信息。

这是我执行该过程的方式:

def dask_stats_calc(dfpath,v1,v2,v3...):
    dfpath_ddf = dd.from_pandas(dfpath,npartitions=16,sort=False)
    return dfpath_ddf.apply(calculate_stats,axis=1,args=(dfdaily,v1,v2,v3...)).compute(get=get).stack().reset_index(drop=True)

f_threaded = partial(dask_stats_calc,dfpath,v1,v2,v3...,multiprocessing.get)
f_threaded()

现在dfpath 是一个有 140 万行的 df,所以dfpath_ddf.apply() 运行超过 140 万行。

一旦整个dfpath_ddf.apply() 完成,就会出现df.to_csv(),但就像您说的那样,最好定期写入磁盘。

现在的问题是,我如何实现每隔 200k 行定期写入磁盘的操作?我想我可以将dfpath_ddf 分解成 200k 块(或类似的东西)并依次运行每个块?

【问题讨论】:

    标签: python pandas memory dask


    【解决方案1】:

    单线程执行

    有时,在等待写入磁盘上的单个文件时,任务会在 RAM 中累积。对于并行系统,使用这样的顺序输出本质上是棘手的。如果您需要使用单个文件,那么我建议您尝试相同的单线程计算,看看它是否有所作为。

    with dask.set_options(get=dask.async.get_sync):
        DF.to_csv('out.csv')
    

    写入多个文件

    您也可以尝试写入 许多 CSV 文件。这在调度上要容易得多,因为任务不必等到其前任完成才能写入磁盘并从 RAM 中删除自己。

    DF.to_csv('out.*.csv')
    

    示例

    因此,一种常见且相当稳健的并行执行和写入方法是将您的计算和最后对to_csv 的调用结合起来

    ddf = dd.from_pandas(df, npartitions=100)
    ddf.apply(myfunc).to_csv('out.*.csv')
    

    这会将您的数据帧分成块,在每个块上调用您的函数,将该块写入磁盘,然后删除中间值,释放空间。

    【讨论】:

    • 感谢您的回答。鉴于您建议定期写入磁盘,我添加了一些附加信息。非常感谢您的帮助。
    • 也许最近添加的文本会有所帮助?
    • 这是完美的。非常感谢你,MRocklin!我很感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 2017-01-04
    • 2011-11-19
    • 1970-01-01
    • 2018-02-02
    • 2021-07-04
    相关资源
    最近更新 更多