Как избежать больших объектов в графе задач

1

Я запускаю симуляции с использованием 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))

Насколько я понимаю (из этого и этого вопроса), метод, предложенный предупреждением, помогает получать большие данные в функцию. Однако мои входы - это все скалярные значения, поэтому они не должны занимать почти 3 МБ памяти. Даже если функция run_model() не принимает никакого аргумента вообще (поэтому никакие параметры не передаются), я получаю такое же предупреждение.

Я также просмотрел график задачи, чтобы узнать, есть ли какой-то шаг, требующий загрузки большого количества данных. Для трех реализаций это выглядит так: Изображение 174551

Поэтому мне кажется, что каждая реализация обрабатывается отдельно, которая должна содержать объем данных, чтобы справиться с минимумом.

Я хотел бы понять, что на самом деле является шагом, который создает большой объект и что мне нужно сделать, чтобы разбить его на более мелкие части.

Теги:
dask
dask-distributed

1 ответ

2
Лучший ответ

Сообщение в этом случае слегка вводит в заблуждение. Проблема проявляется в следующем:

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

и маринованный размер этого графа (голова которого является ключом getitem в сообщении) составляет ~ 3 МБ. Путем создания массива dask для каждого элемента вычисления вы получаете сложный массив с таким количеством разделов, как элементы, а также операции запуска и выбора модели, а также операции хранения применяются к каждому отдельному и сохраняются на графике. Да, они независимы и, вероятно, все это вычисление будет завершено, но это все очень расточительно, если только функция создания модели не работает в течение значительного времени на каждом входном скаляре.

В вашей реальной ситуации может быть, что внутренние массивы на самом деле больше, чем одноэлементная версия, которую вы представляете, но в общем случае выполнения операций numpy на массивах обычно создавать массивы на рабочих (со случайными или некоторая функция загрузки) и работать с разделами размером> 100 МБ.

  • 0
    Спасибо за объяснение. У меня есть несколько вопросов для лучшего понимания вашего ответа: 1) Что вычисляет первая строка вашего кода? 2) Размер всех графов 3MB или размер одного независимого графа?
  • 0
    3) Я уже подозревал, что создание массива dask для каждой реализации было бы немного излишним, хотя мои выходные массивы немного больше (хотя и не на порядки), а функция модели (решение системы ODE) занимает немного больше времени чем в примере. Будет ли ваше предложение означать, что мне нужно вычислить вывод модели для нескольких реализаций внутри функции run_model приведет к увеличению выходных массивов, но уменьшению числа dask-массивов?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню