如何避免任务图中的大物体

时间:2018-08-27 12:45:35

标签: python dask dask-distributed dask-delayed

我正在使用dask.distributed运行模拟。我的模型是在延迟函数中定义的,并且我堆叠了一些实现。 此代码段给出了我的操作的简化版本:

import numpy as np
import xarray as xr
import dask.array as da
import dask
from dask.distributed import Client
from itertools import repeat 

@dask.delayed
def run_model(n_time,a,b):
    result = np.array([a*np.random.randn(n_time)+b])
    return result

client = Client()

# Parameters
n_sims = 10000
n_time = 100
a_vals = np.random.randn(n_sims)
b_vals = np.random.randn(n_sims)
output_file = 'out.nc'

# Run simulations
out = da.stack([da.from_delayed(run_model(n_time,a,b),(1,n_time,),np.float64) for a,b in zip(a_vals, b_vals)])

# Store output in a dataframe
ds = xr.Dataset({'var1': (['realization', 'time'], out[:,0,:])},
             coords={'realization': np.arange(n_sims),
                     'time': np.arange(n_time)*.1})

# Save to a netcdf file -> at this point, computations will be carried out
ds.to_netcdf(output_file)

如果我想运行很多仿真,则会收到以下警告:

/home/user/miniconda3/lib/python3.6/site-packages/distributed/worker.py:840: UserWarning: Large object of size 2.73 MB detected in task graph: 
  ("('getitem-32103d4a23823ad4f97dcb3faed7cf07', 0,  ... cd39>]), False)
Consider scattering large objects ahead of time
with client.scatter to reduce scheduler burden and keep data on workers

    future = client.submit(func, big_data)    # bad

    big_future = client.scatter(big_data)     # good
    future = client.submit(func, big_future)  # good
  % (format_bytes(len(b)), s))

据我了解(来自thisthis问题),警告提出的方法有助于将大量数据放入函数中。但是,我的输入都是标量值,因此它们不应占用将近3MB的内存。即使函数run_model()根本不接受任何参数(因此不传递任何参数),我也会收到相同的警告。

我还查看了任务图,以查看是否有一些步骤需要加载大量数据。对于三个实现,它看起来像这样: Task graph of the code

因此,在我看来,每个实现都是单独处理的,应使要处理的数据量保持较低。

我想了解生产大型物体的步骤实际上是什么,以及将其分解成较小部分所需要做的事情。

1 个答案:

答案 0 :(得分:2)

在这种情况下,该消息有些误导。该问题由以下内容证明:

> len(out[:, 0, :].dask)
40000
> out[:, 0, :].npartitions
10000

,该图的腌制大小(其头部是消息中的getitem键)为〜3MB。通过为计算的每个元素创建一个dask-array,最终得到一个堆叠的数组,该数组具有与元素一样多的分区,并且模型运行操作和项目选择以及存储操作将应用于每个单元并进行存储在图中。是的,它们是独立的,并且可能会完成整个计算,但这都是非常浪费的,除非模型制作功能在每个输入标量上运行相当长的时间。

在您的实际情况下,内部数组实际上可能比您提供的单元素版本大,但是在对数组执行numpy操作的一般情况下,通常在worker上创建数组(具有随机或某些加载功能)并在大小大于100MB的分区上运行。