I want to create a local copy of some of the variables contained in one of the many ERA5 zarr replicas available (here I chose to use the google cloud storage one for convenience). Why? Because we need quick access for analysis and I want to optimize the chunking in the process for our queries.
The idea is to initialize the skeleton and write the metadata to disk without computing
# Chunk specification
CHUNKS = {
"time": 1,
"level": 1,
"latitude": 721,
"longitude": 1440
}
for var_name in VARIABLES:
da_var = ds_filtered[var_name]
var_chunks = tuple([CHUNKS.get(d, da_var.sizes[d]) for d in da_var.dims])
data_vars[var_name] = (
da_var.dims,
da.empty(da_var.shape, dtype=da_var.dtype, chunks=var_chunks)
)
ds_empty = xr.Dataset(data_vars=data_vars, coords=coords, attrs=ds_filtered.attrs)
ds_empty.to_zarr(TARGET_ZARR, compute=False, consolidated=True, mode='w', zarr_format=2)
And then start writing with multiple workers in parallel to different regions
def process_time_chunk_like_api(time_index):
global worker_ds
ds_hour = worker_ds.isel(time=slice(time_index, time_index + 1))
# Eagerly load the hour strictly into RAM.
with dask.config.set(scheduler='single-threaded'):
ds_hour = ds_hour.load()
ds_hour = ds_hour.chunk(CHUNKS)
ds_hour.to_zarr(TARGET_ZARR, region='auto', zarr_format=2)
This works but it’s not really scalable as it uses an insane amount of memory in the beginning and surely isn’t optimized. Even though the original gcs chunks contain all vertical levels in one, expanding them into memory shouldn’t cause the consumption I"m seeing.
I felt like this is something that rechunker was supposed to do, but I believe that library is outdated. Cubed does not seem to support multiple workers writing to the same zarr.
Surely I’m doing something wrong as this seems to be a recurring issue. What is the most efficient way of copying a zarr from one remote to another while rechunking and using the least amount of resources possible?