为大型 hdf5 文件重命名组中的所有 HDF5 数据集时出现问题
Posted
技术标签:
【中文标题】为大型 hdf5 文件重命名组中的所有 HDF5 数据集时出现问题【英文标题】:Problem renaming all HDF5 datasets in group for large hdf5 files 【发布时间】:2019-04-04 18:32:18 【问题描述】:我在重命名 hdf5 中的数据集时遇到问题。这个过程非常缓慢。我阅读了一些文档,指出数据集名称只是指向数据的链接,因此一种可接受的重命名方式是:
group['new_name'] = group['old_name']
del group['old_name']
但这太慢了(一夜之间只完成了 5%),这让我觉得我的过程完全错误。
我正在使用 python h5py,这是我的慢代码:
# Open file
with h5py.File('test.hdf5') as f:
# Get all top level groups
top_keys = [key for key in f.keys()]
# Iterate over each group
for top_key in top_keys:
group = f[top_key]
tot_digits = len(group)
#Rename all datasets in the group (pad with zeros)
for key in tqdm(group.keys()):
new_key = str(key)
while len(new_key)<tot_digits:
new_key = '0'+str(new_key)
group[new_key] = group[key]
del group[key]
根据@jpp 的建议,我还尝试用group.move
替换最后两行:
group.move(key, new_key)
但是这种方法同样慢。我有几个具有相同数量数据集的组,但每个组都有不同大小的数据集。拥有最大数据集(最多字节)的组似乎重命名最慢。
当然有一种方法可以快速做到这一点。数据集名称只是一个符号链接吗?还是重命名本身会导致整个数据集被重写?我应该如何重命名 HDF5 文件中的多个数据集?
【问题讨论】:
您的组中有多少个数据集?如果您有一些代码来创建一个简单的 HDF5 文件,那就太好了,这样我们就可以对其进行基准测试(并同时展示您的问题)。 我每组只有 1M 个数据集,而我的 hdf5 文件约为 20GB,因此共享数据集很困难。关键问题更多地与命名数据集的行为方式有关。名称只是一个符号链接吗?还是重命名本身会导致整个数据集被重写? @jpp 不确定这是否仍然相关,但我过去在命名 HDF5 组时遇到了问题,名称以数字开头,如果没有其他方法似乎可以尝试不同的命名方案。跨度> @Joules 我的组用字母命名,但我的数据集用数字命名。您是否也遇到过数据集名称的问题?还是只是组? IIRC 它不允许我保存名称以数字作为第一个字符的数据集或组。我可能一直在使用pandas
HDF5,所以我不确定它是否会与 h5py 产生相同的反应。
【参考方案1】:
一个可能的罪魁祸首是,至少如果您的***键下有大量组,那么您正在以非常低效的方式创建新名称。而不是
while len(new_key)<tot_digits:
new_key = '0'+str(new_key)
您应该像这样生成新密钥:
if len(new_key)<tot_digits:
new_key = (tot_digits-len(new_key))*'0' + new_key
这样您就不会为需要添加的每个额外数字创建一个新的字符串对象。
也有可能,尽管我无法确认,调用group.keys()
将返回一个迭代器,该迭代器将使用您添加的新键名重新填充,因为您在迭代键时修改了组。一个标准的 python 迭代器会抛出一个 RuntimeError,但很明显 hf5py 是否会这样做。为确保您没有这个问题,您可以简单地确保预先创建一个键列表。
for key in tqdm(list(group.keys())):
【讨论】:
感谢您的建议!我实现了它们,但没有重大改进。循环仍然以每秒大约 1 次迭代的速度运行,这意味着整个操作大约需要一天时间。我已经重命名了组中的前 1K 左右,所以第一次迭代运行得非常快,然后一旦开始重命名数据集,它就会陷入困境。 @Richard 你说这是每秒重命名一次。当您手动操作时,即从交互式外壳中进行操作时也是如此吗?【参考方案2】:这个怎么样?组的查找可能比简单的迭代花费更长的时间吗?我做了一些优化——因为我没有测试文件,所以我不能真正尝试。
# Open file
with h5py.File('test.hdf5') as f:
# Iterate over each group
for top_key, group in f.items():
#Rename all datasets in the group (pad with zeros)
for key in tqdm(group.keys()):
new_key = (":0<" + str(len(group)) + "").format(str(key))
group.move(key, new_key)
【讨论】:
感谢埃米尔的回答!我在这里看不到任何额外的优化。只有 4 个组,每个组有大约 1M 数据集。数据集的重命名很慢,我们都以同样的方式找到group.keys
。您的想法似乎与我们已经尝试过的 ilmarinen 的想法相似。
哦...4组真的不是...我认为top_keys = [key for key in f.keys()]
和group = f[top_key]
可能会减慢速度,但是只有4组,然后是的...那是绝对不是。但是如果只有 4 个组,您能否对数字进行一些估计,例如 G1:100 万个条目,G2:130 万个等...还有一件事,您是否尝试过删除 tqdm(以防万一),并设置一个手动计数器,即有i +=1
和if i % 100 == 0: print("At number: ".format(i))
或类似的东西以上是关于为大型 hdf5 文件重命名组中的所有 HDF5 数据集时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
是否可以直接重命名存储在 hdf5 文件中的 pandas 数据框的列?
访问 netcdf 文件中嵌套组中的变量(文件格式 HDF5)
将 HDF5 文件中的大型数据集读入 x_train 并在 keras 模型中使用
TensorFlow - tf.data.Dataset 读取大型 HDF5 文件