使用 h5py 将切片写入现有的 hdf5 数据化非常慢
Very slow writing of a slice into an existing hdf5 datased using h5py
我有一个 (22500, 516, 516), uint16 h5py 数据集,我想在处理数据后逐个替换它。
为此,我按以下方式加载了几个数据块(块形状为 (1,129,129)):
chunk = data[:,
i1*129:(i1+1)*129,
i2*129:(i2+1)*129].astype(pl.float32)
其中 data
是数据集和 i1, i2
索引,它们 运行 在新循环中从 0 到 3。
稍后在循环中我写入处理后的数据:
data[:,
i1*129:(i1+1)*129,
i2*129:(i2+1)*129] = chunk.astype(pl.uint16)
在这里,我经历了很长的延迟,进程将变得不可中断(状态 D)并导致 0% cpu 负载。内存使用率约为 1%。
更重要的是,与这台 PC 或安装了相同驱动器的服务器的不同 ssh 会话几乎没有响应。好像冻结了一段时间。
但是,如果我在循环之前创建一个新数据集
datanew = entry.create_dataset("data_new",
shape=data.shape,
chunks=data.chunks,
dtype=data.dtype,
compression="gzip",
compression_opts=4)
改为写入此数据集,我没有遇到任何问题并且性能非常好。
新数据集的唯一区别是原始数据集使用了 lzf
压缩。
有什么方法可以理解这里出了什么问题吗?
谢谢
您的 HDF5 文件在哪个存储设备上(本地 ssd/harddisk 或 NAS)?
也许您 运行 由于文件碎片而遇到问题。块通常按顺序读取和写入。
如果您用更大的压缩块覆盖压缩块(使用压缩数据集时可能会发生这种情况),块可能最终会在磁盘上变成碎片。性能影响将取决于您的存储设备(NAS >> 本地硬盘 >> SSD)的延迟。
如果您看到这种效果,我会推荐以下内容:
- 将结果写入临时文件
- 删除原始数据集(注意这里文件大小并没有减少)
- 将临时文件中的数据集复制到主 h5 文件中
- 删除临时文件
您可能还想增加区块大小,以便在访问具有高延迟的存储设备上的文件时获得更好的性能。如果您仅以上述方式访问数据集,则可以将块大小增加到例如 (50,129,129) 甚至更多。
关于不同存储设备上的块大小的一些简单基准测试:
我有一个 (22500, 516, 516), uint16 h5py 数据集,我想在处理数据后逐个替换它。
为此,我按以下方式加载了几个数据块(块形状为 (1,129,129)):
chunk = data[:,
i1*129:(i1+1)*129,
i2*129:(i2+1)*129].astype(pl.float32)
其中 data
是数据集和 i1, i2
索引,它们 运行 在新循环中从 0 到 3。
稍后在循环中我写入处理后的数据:
data[:,
i1*129:(i1+1)*129,
i2*129:(i2+1)*129] = chunk.astype(pl.uint16)
在这里,我经历了很长的延迟,进程将变得不可中断(状态 D)并导致 0% cpu 负载。内存使用率约为 1%。 更重要的是,与这台 PC 或安装了相同驱动器的服务器的不同 ssh 会话几乎没有响应。好像冻结了一段时间。
但是,如果我在循环之前创建一个新数据集
datanew = entry.create_dataset("data_new",
shape=data.shape,
chunks=data.chunks,
dtype=data.dtype,
compression="gzip",
compression_opts=4)
改为写入此数据集,我没有遇到任何问题并且性能非常好。
新数据集的唯一区别是原始数据集使用了 lzf
压缩。
有什么方法可以理解这里出了什么问题吗?
谢谢
您的 HDF5 文件在哪个存储设备上(本地 ssd/harddisk 或 NAS)?
也许您 运行 由于文件碎片而遇到问题。块通常按顺序读取和写入。
如果您用更大的压缩块覆盖压缩块(使用压缩数据集时可能会发生这种情况),块可能最终会在磁盘上变成碎片。性能影响将取决于您的存储设备(NAS >> 本地硬盘 >> SSD)的延迟。
如果您看到这种效果,我会推荐以下内容:
- 将结果写入临时文件
- 删除原始数据集(注意这里文件大小并没有减少)
- 将临时文件中的数据集复制到主 h5 文件中
- 删除临时文件
您可能还想增加区块大小,以便在访问具有高延迟的存储设备上的文件时获得更好的性能。如果您仅以上述方式访问数据集,则可以将块大小增加到例如 (50,129,129) 甚至更多。 关于不同存储设备上的块大小的一些简单基准测试: