我正在尝试存储在磁盘上的 3 维 zarr 数组:
Name: /data
Type: zarr.core.Array
Data type: int16
Shape: (102174, 1100, 900)
Chunk shape: (12, 220, 180)
Order: C
Read-only: True
Compressor: Blosc(cname='zstd', clevel=3, shuffle=BITSHUFFLE, blocksize=0)
Store type: zarr.storage.DirectoryStore
No. bytes: 202304520000 (188.4G)
No. bytes stored: 12224487305 (11.4G)
Storage ratio: 16.5
Chunks initialized: 212875/212875
据我了解,zarr-arrays 也可以驻留在内存中 - 压缩,就好像它们在磁盘上一样。所以我想为什么不尝试将整个东西加载到具有 32 GB 内存的机器上的 RAM 中。压缩后,数据集将需要大约50% 的 RAM。未压缩时,它需要的 RAM 大约是可用 RAM 的 6 倍。
准备:
import os
import zarr
from numcodecs import Blosc
import tqdm
zpath = '...' # path to zarr data folder
disk_array = zarr.open(zpath, mode = 'r')['data']
c = Blosc(cname = 'zstd', clevel=3, shuffle = Blosc.BITSHUFFLE)
memory_array = zarr.zeros(
disk_array.shape, chunks = disk_array.chunks,
dtype = disk_array.dtype, compressor = c
)
以下实验几乎立即失败并出现内存不足错误:
memory_array[:, :, :] = disk_array[:, :, :]
据我了解,disk_array[:, :, :]
将尝试创建一个未压缩的全尺寸 numpy 数组,这显然会失败。
第二次尝试,有效但速度非常慢:
chunk_lines = disk_array.chunks[0]
chunk_number = disk_array.shape[0] // disk_array.chunks[0]
chunk_remain = disk_array.shape[0] % disk_array.chunks[0] # unhandled ...
for chunk in tqdm.trange(chunk_number):
chunk_slice = slice(chunk * chunk_lines, (chunk + 1) * chunk_lines)
memory_array[chunk_slice, :, :] = disk_array[chunk_slice, :, :]
在这里,我试图一次读取一定数量的块并将它们放入我的内存数组中。它可以工作,但它比最初将这个东西写入磁盘所用的速度要慢 6 到 7 倍。编辑:是的,它仍然很慢,但是由于磁盘问题发生了 6 到 7 次。
实现这一目标的智能且快速的方法是什么?我猜,除了没有使用正确的方法之外,我的块也可能太小了——但我不确定。
编辑:磁盘阵列和内存阵列的形状、块大小和压缩应该是相同的。因此,在我上面的示例中应该可以消除解压缩过程。
我找到了,zarr.convenience.copy
但它被标记为experimental feature
,可能会进一步更改。