如何使用Dask.array有效地将大型numpy数组发送到集群

时间:2017-08-29 14:20:24

标签: numpy dask

我的本​​地计算机上有一个很大的NumPy数组,我希望在集群上与Dask.array并行化

import numpy as np
x = np.random.random((1000, 1000, 1000))

然而,当我使用dask.array时,我发现我的调度程序开始占用大量内存。为什么是这样?这些数据不应该发给工人吗?

import dask.array as da
x = da.from_array(x, chunks=(100, 100, 100))

from dask.distributed import Client
client = Client(...)
x = x.persist()

1 个答案:

答案 0 :(得分:4)

每当你{Dtml>集合persistcompute时,数据都会传递给调度程序,并从那里传递给工作者。如果您想绕过在调度程序上存储数据,则必须了解move datascatter的合作方式。

您有三种选择:

  1. 不要在客户端计算机上加载数据
  2. 分散然后-块
  3. 块状然后散射
  4. 不要在客户端计算机上加载数据

    最好的方法是将数据作为计算的一部分加载,而不是在本地进行。

    之前
    x = load_array_from_file(fn)  # load into a local numpy array
    x = da.from_array(x, chunks=(100, 100, 100))  # split with dask
    x = x.persist()
    
    x = dask.delayed(load_array_from_file)(fn)
    x = da.from_delayed(x, shape=(1000, 1000, 1000), dtype=float)
    x = x.rechunk((100, 100, 100))
    x = x.persist()
    

    有关创建dask数组的更多信息,请访问:http://dask.pydata.org/en/latest/array-creation.html

    Scatter然后chunk

    您可以将numpy数组直接分散到worker

    future = client.scatter(x)
    x = da.from_delayed(future, shape=x.shape, dtype=x.dtype)
    x = x.rechunk((100, 100, 100))
    x = x.persist()
    

    这会将您的数据直接移动到工作人员,然后从那里开始。这很好,因为它绕过了调度程序。但是,如果您的员工开始失败,您现在面临数据丢失的风险。这只有在大规模并行系统中才有意义。

    这也有点低效,因为你所有的数据都在一个工人身上,而不是分散开来。您可以致电client.rebalance或继续阅读。

    Chunk然后分散

    您可以使用本地调度程序在本地对数据进行分块,然后分散到群集中。

    x = da.from_array(x, chunks=(100, 100, 100))
    x = x.persist(get=dask.threaded.get)  # chunk locally
    futures = client.scatter(dict(x.dask))  # scatter chunks
    x.dask = x  # re-attach scattered futures as task graph
    

    留在当地

    或者,您可以继续在本地使用dask,可以使用线程调度程序,也可以使用仅使用本地进程的分布式调度程序。

    client = Client(processes=False)
    

    这将阻止在本地进程,调度程序和工作程序之间进行不必要的数据复制。他们现在都处于同一个本地流程中。

    另请参阅:How to efficiently submit tasks with large arguments in Dask distributed?,了解此答案的基于任务的版本