【问题标题】:Running out of memory when using Dask arrays使用 Dask 数组时内存不足
【发布时间】:2021-07-08 17:08:15
【问题描述】:

我需要对大于内存的张量执行一些计算,但首先我需要从适合内存的NumPy 数组(部分)构造它。

我正在计算这些NumPy 数组,然后将它们转换为Dask 数组,并将它们放在list 上。我的最终张量是这些数组的特定串联。问题是,根据部分的数量,我什至无法到达发生连接的代码行。

例如,使用形状为(30, 40, 40, 40, 40) 的部分,大约614 MB,使用16 GB 的RAM(通常10 空闲),仅尝试计算20 部分就足以耗尽内存.

我可以看到每个新张量的计算如何变慢,以及可用 RAM 如何越来越低,直到进程被终止。如果我计算10 部分,我可以看到我的可用RAM10 GB 下降到5.2。如果我尝试计算 20 部分,该进程将被终止。

import numpy as np
import dask.array as da

def compute_part():
    array = np.random.random((30, 40, 40, 40, 40)) # 614 MB
    return da.from_array(array)

def construct_tensor(nparts):
    list_of_parts = []
    for part in range(nparts):
        part_as_da_array = compute_part()
        list_of_parts.append(part_as_da_array)
    # Below, the concatenation should happen

construct_tensor(20) # This is enough for the process to not finish

有没有办法更好地利用可用内存? Dask 自动创建大小为(15, 20, 20, 20, 20)chunks,并且我还尝试对数组进行重新分块以使每一块都更小,但我没有看到任何改进。目前,我在内存使用方面使用 Dask 数组而不是 NumPy 数组时几乎没有区别。

【问题讨论】:

    标签: python arrays numpy dask


    【解决方案1】:

    dask 无法“减少”您已经在内存中呈现给它的数组的大小。没有分块会帮助你。 如果您的数据适合内存,也许您根本不需要 Dask。

    相反,您需要在每个块中根据需要加载/创建数据。对于您的简单示例,您可以通过将 compute_part 替换为 da.random.random 来实现此目的,这正是这种方式的惰性(在实际使用每个块之前不使用任何内存)。

    我很欣赏随机数可能不是您的实际用例。如果这些片段确实需要首先在内存中,您可能最终会使用da.from_delayed,或者首先为每个块运行您的块创建步骤,写入支持按块写入的 zarr 之类的数据存储。

    【讨论】:

    • 好的,我明白了,我以为磁盘溢出了。我没有使用随机数,而是使用更复杂的计算,但是,我从您的回答中得到了一些想法。
    猜你喜欢
    • 2020-01-25
    • 2022-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多