使用dask数组时内存不足

zour9fqk  于 2021-08-25  发布在  Java
关注(0)|答案(1)|浏览(375)

我需要在一个大于内存的Tensor上进行一些计算,但首先我需要从 NumPy 适合内存的阵列(部件)。
我在计算这些 NumPy 数组,然后将它们转换为 Dask 数组,并将它们放在 list . 我的最后一个Tensor是这些数组的特殊连接。问题是,根据部分的数量,我甚至无法到达发生串联的代码行。
例如,使用形状的零件 (30, 40, 40, 40, 40) ,那么 614 MB 具有 16 GB ram(通常为 10 免费),只是尝试计算 20 部件足够耗尽内存。
我可以看到每个新Tensor的计算是如何变慢的,以及可用ram是如何变得越来越低,直到进程被终止。如果我计算 10 零件,我可以看到我的可用零件 RAM10 GB5.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自动创建 chunks 大小 (15, 20, 20, 20, 20) ,我还尝试重新调整阵列,使每一块都更小,但我没有看到任何改进。当我使用时,我现在看到的差别很小 Dask 数组而不是 NumPy 在内存使用方面。

erhoui1w

erhoui1w1#

dask无法“减少”内存中已存在的阵列的大小。没有分块会对你有帮助。如果您的数据适合内存,那么您可能根本不需要dask。
相反,您需要在每个块中根据需要加载/创建数据。对于您的简单示例,您可以通过替换 compute_part 具有 da.random.random ,它正是以这种方式懒惰的(在实际使用每个块之前不使用任何内存)。
我理解随机数可能不是您的实际用例。如果这些片段确实需要先存储在内存中,那么最终可能会使用 da.from_delayed ,或者首先为每个块运行块创建步骤,写入数据存储,如支持块写入的zarr。

相关问题