我的本地计算机上有一个很大的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()
答案 0 :(得分:4)
每当你{Dtml>集合persist
或compute
时,数据都会传递给调度程序,并从那里传递给工作者。如果您想绕过在调度程序上存储数据,则必须了解move data与scatter的合作方式。
您有三种选择:
最好的方法是将数据作为计算的一部分加载,而不是在本地进行。
之前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
您可以将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
或继续阅读。
您可以使用本地调度程序在本地对数据进行分块,然后分散到群集中。
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?,了解此答案的基于任务的版本