Неожиданное поведение при фрагментировании нескольких файлов netcdf в xarray / dask

Я работаю с набором из 468 файлов netcdf общим размером до 12 ГБ. Каждый файл имеет только один глобальный снимок геофизической переменной, т.е. для каждого файла форма данных (1, 1801, 3600) соответствует размерам ('time', 'latitude', 'longitude').

Моя оперативная память составляет 8 ГБ, поэтому мне нужно разбить ее на части. Я создаю набор данных xarray, используя xarray.open_mfdataset, и обнаружил, что использование блока параметров при вызове xarray.open_mfdataset или повторном преобразовании после метода .chunk дает совершенно разные результаты. Об аналогичных проблемах сообщалось здесь, не получив ответа.

Из документации xarray чанкинг при вызове xarray.open_dataset или повторном чанковании с .chunk должны быть точно эквивалентными ...

http://xarray.pydata.org/en/stable/dask.html введите описание изображения здесь

... но это не так. Поделюсь здесь своими примерами.

import xarray as xr

data1 = xr.open_mfdataset('/data/cds_downloads/2m_temperature/*.nc',
                          concat_dim='time', combine='nested',
                          chunks = {'longitude':400, 'latitude':200}) \
                         .chunk({'time':-1})
data1.t2m.data

введите описание изображения здесь

with ProgressBar():
    data1.std('time').compute()

[########################################] | 100% Completed |  5min 44.1s

В этом случае все работает нормально.

2) ИЗМЕРЕНИЕ МЕТОДОМ .chunk ПО ПРОСТРАНСТВЕННЫМ ИЗМЕРЕНИЯМ (долгота, широта) БЕЗ РАЗРЕШЕНИЯ ВРЕМЕНИ.

data2=xr.open_mfdataset('/data/cds_downloads/2m_temperature/*.nc',
                        concat_dim='time',combine='nested') \
                       .chunk({'time': -1, 'longitude':400, 'latitude':200})
data2.t2m.data

введите описание изображения здесь

Как показано на этом изображении, очевидно, что теперь фрагменты точно такие же, как в 1). Тем не мение...

with ProgressBar():
    data2.std('time').compute()

[#####################################   ] | 93% Completed |  1min 50.8s

... вычисление std не могло завершиться, ядро ​​ноутбука jupyter умерло без сообщения из-за превышения лимита памяти, поскольку я мог проверить мониторинг с помощью _14 _... Это, вероятно, означает, что разбиение на части действительно не происходило, и все набор данных без фрагментов загружается в память.

3) РАЗДЕЛЕНИЕ ПРИ ВЫЗОВЕ xarray.open_mfdataset ПО ПРОСТРАНСТВЕННЫМ ИЗМЕРЕНИЯМ (долгота, широта) И ОСТАВЛЕНИЕ ИЗМЕРЕНИЯ ВРЕМЕНИ, РАЗБИРАЕМОГО ПО УМОЛЧАНИЮ (ОДИН ФАЙЛ НА ФАЙЛ).

Теоретически этот случай должен быть намного медленнее, чем 1), поскольку вычисление std выполняется по временному измерению, и, таким образом, гораздо больше фрагментов генерируется без необходимости (сейчас 421420 фрагментов против 90 фрагментов в (1)).

data3 = xr.open_mfdataset('/data/cds_downloads/2m_temperature/*.nc',
                          concat_dim='time', combine='nested',
                          chunks = {'longitude':400, 'latitude':200})
data3.t2m.data

введите описание изображения здесь

with ProgressBar():
    data3.std('time').compute()

[########################################] | 100% Completed |  5min 51.2s

Однако проблем с памятью нет, и время, необходимое для вычислений, почти такое же, как в случае 1). Это снова говорит о том, что метод .chunk, похоже, не работает должным образом.

Кто-нибудь знает, имеет ли это смысл или как решить эту проблему? Мне нужно было бы иметь возможность изменять фрагменты в зависимости от конкретных вычислений, которые мне нужно выполнить.

Спасибо

PD: Я использую xarray версии 0.15.1


person susopeiz    schedule 16.07.2020    source источник
comment
Я тестировал использование xr.open_dataset с одним большим файлом netcdf (вместо набора из сотен более мелких файлов netcdf), и возникает та же проблема. Метод .chunk не оказывает заметного влияния на производительность.   -  person susopeiz    schedule 17.07.2020
comment
Я нашел что-то похожее с фрагментированием open_mfdataset по сравнению с последующим. Этот первый был медленнее, я думаю, но я не мог его точно определить, к тому же я только начинал изучать xarray. Мой нынешний подход состоит в том, чтобы не беспокоить фрагменты во время открытия (поскольку на самом деле ничего еще не прочитано?) И фрагменты после, особенно при удалении фрагментов времени .chunk ({'time': - 1}. Это, казалось, имело большой эффект для по какой-то причине. Затем я использую .persist () или .compute (), когда что-то действительно происходит.   -  person Paul    schedule 23.07.2020
comment
Итак, @Paul вы имеете в виду, что в вашем случае использование .chunk после вызова open_mfdataset оказывает явное влияние на производительность при вычислениях? Я был бы весьма удивлен, если бы это было так. Рабочее решение, которое я нашел, противоположное; Просто забудьте о .chunk и создайте другой объект datarray, вызывающий open_mfdataset с разными значениями, передаваемыми в параметр chunk внутри. В моем случае это действительно работает нормально.   -  person susopeiz    schedule 23.07.2020


Ответы (1)


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

Да, вычисления будут очень чувствительны к структуре блоков.

Как можно раньше разбивать вычисления на части (в идеале, когда вы читаете данные) - это идеальный вариант, потому что это упрощает общее вычисление.

В общем, я рекомендую куски большего размера. См. https://docs.dask.org/en/latest/best-practices.html#avoid-very-large-graphs

person MRocklin    schedule 08.08.2020