通过码头化的fastAPI应用程序内的python-xarray缓慢读取小型zarr/S3数据



我有一个像这样的小数据集:

<xarray.Dataset>
Dimensions:      (time: 24)
Coordinates:
* time         (time) datetime64[ns] 2022-09-28 ... 2022-09-28T23:00:00
spatial_ref  int64 0
Data variables:
CO           (time) float32 dask.array<chunksize=(24,), meta=np.ndarray>
NO2          (time) float32 dask.array<chunksize=(24,), meta=np.ndarray>
O3           (time) float32 dask.array<chunksize=(24,), meta=np.ndarray>
PM10         (time) float32 dask.array<chunksize=(24,), meta=np.ndarray>
PM2.5        (time) float32 dask.array<chunksize=(24,), meta=np.ndarray>
SO2          (time) float32 dask.array<chunksize=(24,), meta=np.ndarray>

该数据集是在S3服务器上托管的原始大型zarr数据集上的一些ds.where()ds.rio.clip()和最终ds.mean(dim=['latitude', 'longitude'])之后获得的。

然后我想访问每个单独的值。我看到

ds['CO'].sel(time=timeToGet).data具有正常速度,但

ds['CO'].sel(time=timeToGet).values

float(ds['CO'].sel(time=timeToGet).data))均耗时1分15秒!为什么会这样?

我以前试过这些:

ds = ds.chunk(chunks={"time": 1})
ds = ds.chunk(chunks='auto')
ds = ds.copy(deep=True)

但没有成功。

对较大数据集的ds.where((调用也很慢,我用ds.chunk('auto')解决了这个问题。我意识到它在我的dockerized应用程序中很慢,但在桌面上进行本地测试时却没有。所以也许docker有影响。事实上,我不明白我的小数据集是在服务器上还是在我电脑的内存中?

这些变量是dask.arrays,而不是numpy,因此尚未加载到内存中。我不确定你是如何准备这个数据集的,但计算数据可能涉及从磁盘加载到互联网流到计算大型计划图的所有内容。

这么小的数据肯定会放入内存,所以你可以通过计算所有变量一次,然后使用本地副本来提高重复访问的性能:

ds = ds.compute()

如果你已经从磁盘上读取了这些数据,并且它当时足够小,可以轻松地放入内存,那么你可以通过指定chunks=None来加载不带dask的数据集,例如:

ds = xr.open_zarr(fp, chunks=None)

此外,dask在容器中运行良好,但它确实需要资源。为了安排任务并并行执行,dask启动多个线程或进程(取决于您的配置(。如果授予容器的资源太少,那么dask可能会慢到爬行,因为它必须将数据溢出到磁盘或与主线程共享处理器。因此,如果你打算继续使用dask,最好关注你的机器资源并查看dask面板。

最新更新