Python 获取海量HDF5文件的组名

Python 获取海量HDF5文件的组名,python,c++,hdf5,h5py,Python,C++,Hdf5,H5py,我有HDF5文件,其大小可能超过50 Gb。我只对抓取其中一个顶级组中所有组的名称感兴趣。例如: f = h5py.File('my_file.hdf') names = f['top_level_group'].keys() 有超过1000000个组,运行上述代码需要数小时才能完成。有没有办法在合理的时间内做到这一点?我觉得只要几秒钟就可以得到所有团体的名字 编辑 我的实际生产代码是C++,使用C++ HDF5API,包括函数 GETObjNeByIdx()/Cuth>。这使我能够计算读取每

我有HDF5文件,其大小可能超过50 Gb。我只对抓取其中一个顶级组中所有组的名称感兴趣。例如:

f = h5py.File('my_file.hdf')
names = f['top_level_group'].keys()
有超过1000000个组,运行上述代码需要数小时才能完成。有没有办法在合理的时间内做到这一点?我觉得只要几秒钟就可以得到所有团体的名字

编辑

我的实际生产代码是C++,使用C++ HDF5API,包括函数<代码> GETObjNeByIdx()/Cuth>。这使我能够计算读取每个组名并输出到日志文件所需的时间。我让它在周末运行,代码还没有完成。我目前的计时结果如下:

起初,代码开始于每个组大约1-1.5毫秒。这对我来说似乎很慢,因为这意味着阅读所有的组大约需要30-35分钟。不管怎样,不久之后,它是在2毫秒(在这一点上,我回家过周末,计算我将有一个完整的图表到周一)

瞧,我错了。注意,这是一个半对数图,对数形状实际上代表一个线性趋势。有趣的是,在某个时刻,它突然从每次读取10毫秒跳到每次读取2.5秒(跳到25秒!)。日志中的读取时间总和为64.5小时

我无法在生成的其他文件中重现此问题(但是,我们至少有3个生产文件存在此问题)。我生成了与有问题的生产文件大小和结构相同的文件,并使用生产代码中相同的函数生成它们,。加载这些测试文件需要1-2秒

我知道这些文件并没有完全损坏,因为只要我们让它运行到完成,我们就会得到结果。数据就在那里,只是需要很长时间才能访问


在这一点上,由于我无法在测试文件中重现该问题,我的问题对于StackOverflow可能是无效的,但我完全不知道该怎么做。

这很奇怪。获取组名/密钥不需要几个小时。 除了访问群组,你还在做什么

下面是一个非常简单的示例,创建1000000个组,关闭HDF5文件并重新打开以获取密钥。它在我的Windows笔记本电脑(24GB内存)上运行大约一分钟

基于OP对数据集的评论,我修改了上面的代码,为每个组添加一个数据集(加上一些定时输出)。然后我跑了不同的组(增加h5文件大小)。时间数据汇总如下。请注意,对于50GB文件中的1000000个组(而对于0.5GB文件中的10000个组),访问组/密钥的时间几乎没有变化。但是,还有其他性能瓶颈(如名称长度计数所示)

10000组(0.5GB)
创建组和数据的时间=4.13
访问组的时间=0.000831
计数组的时间=0.0227

100000组(5GB)
创建组和数据的时间=44.88
访问组的时间=0.000678
计数组的时间=0.266

1000000组(50GB)
创建组和数据的时间=983.8
访问组的时间=0.00109
计数组的时间=724.9

修改了下面的代码

size = 1000000
dim=80
arr=np.random.rand(dim*dim,1).reshape(dim,dim)

start = time.clock()
with h5py.File('SO_59668177.h5','w') as h5f:
    for g_cnt in range(size):
        grp=h5f.create_group('grp_' +str(g_cnt))
        grp.create_dataset('dset_1',data=arr)
print ('create groups and data')
print ('Elapsed time =', (time.clock() - start) )

start = time.clock() 
with h5py.File('SO_59668177.h5','r') as h5f:
    names = h5f.keys()
    print ('access groups')
    print ('Elapsed time =', (time.clock() - start) )

    start = time.clock() 
    print (len(names))
    print ('count groups')
    print ('Elapsed time =', (time.clock() - start) )

一分钟似乎仍然很荒谬,不是吗?不管怎样,我想为什么你的文件只需要一分钟,是因为文件中没有50 Gb的数据。如果删除打印语句,它实际上只需一两秒钟就可以加载,这取决于你的比较。:)我试着用HDF查看器(用Java编写)打开我的示例文件,但它仍然在显示(6分钟后)。我非常确信读取时间取决于每个组的大小。我的生产代码是C++,允许我一次读取单个组。我发现不同的子集(所有相同数量的组)加载所需的时间大大不同,这取决于组的大小。“删除打印语句”——这并不奇怪。所以在我的例子中,时间是用来数钥匙,而不是去拿钥匙。下一个(反问)问题是:你有一个50GB的文件需要更长的时间吗?每个组中有多少数据集?用
h5ls-r myfile.hdf
列出所有组需要多长时间?这给出了一个可能的下限的概念。从当前的打印速率推断,很可能需要一两个小时。然而,仅仅访问组名本身应该比打印它们快几个数量级。尝试重定向到/dev/null。(
h5ls-r myfile.hdf>/dev/null
)以排除打印和滚动的任何影响。41分钟用于/dev/null重定向
size = 1000000
dim=80
arr=np.random.rand(dim*dim,1).reshape(dim,dim)

start = time.clock()
with h5py.File('SO_59668177.h5','w') as h5f:
    for g_cnt in range(size):
        grp=h5f.create_group('grp_' +str(g_cnt))
        grp.create_dataset('dset_1',data=arr)
print ('create groups and data')
print ('Elapsed time =', (time.clock() - start) )

start = time.clock() 
with h5py.File('SO_59668177.h5','r') as h5f:
    names = h5f.keys()
    print ('access groups')
    print ('Elapsed time =', (time.clock() - start) )

    start = time.clock() 
    print (len(names))
    print ('count groups')
    print ('Elapsed time =', (time.clock() - start) )