h5py 将虚拟数据集读入 NumPy 数组时出错

问题描述 投票:0回答:2

我正在尝试从使用 h5py 创建的虚拟 HDF 数据集加载数据,但在正确加载数据时遇到一些问题。

这是我的问题的一个例子:

import h5py
import tools as ut

virtual  = h5py.File(ut.params.paths.virtual)

a = virtual['part2/index'][:]

print(virtual['part2/index'][-1])
print(a[-1])

输出:

[890176134]
[0]

为什么?为什么当我将数据复制到 NumPy 数组 (value=

[0]
) 与直接从数据集读取 (value=
[890176134]
) 时最后一个元素不同?

我是否在没有意识到的情况下做了一些严重错误的事情?

非常感谢。

python hdf5 h5py
2个回答
1
投票

是的,您应该从虚拟数据集或从虚拟数据集创建的数组中获取相同的值。如果没有更多有关数据的详细信息,很难诊断错误。

我使用 h5py 示例

vds_simple.py
来演示它应该如何表现。大部分代码构建 HDF5 文件。最后的部分比较输出。下面的代码根据示例进行修改,以创建可变数量的源文件(由
a0=
定义)。

使用示例数据创建“a0”源文件的代码:

a0 = 5000
# create sample data
data = np.arange(0, 100).reshape(1, 100)

# Create source files (0.h5 to a0.h5)
for n in range(a0):
    with h5py.File(f"{n}.h5", "w") as f:
        row_data = data + n
        f.create_dataset("data", data=row_data)

定义虚拟布局和组装虚拟数据集的代码:

# Assemble virtual dataset
layout = h5py.VirtualLayout(shape=(a0, 100), dtype="i4")
for n in range(a0):
    filename = "{}.h5".format(n)
    vsource = h5py.VirtualSource(filename, "data", shape=(100,))
    layout[n] = vsource

# Add virtual dataset to output file
with h5py.File("VDS.h5", "w", libver="latest") as f:
    f.create_virtual_dataset("vdata", layout)

读取并打印数据的代码:

# read data back
# virtual dataset is transparent for reader!
with h5py.File("VDS.h5", "r") as f:
    arr = f["vdata"][:]

    print("\nFirst 10 Elements in First Row:")
    print("Virtual dataset:")
    print(f["vdata"][0, :10])
    print("Reading vdata into Array:")
    print(arr[0, :10])

    print("Last 10 Elements of Last Row:")
    print("Virtual dataset:")
    print(f["vdata"][-1,-10:])
    print("Reading vdata into Array:")
    print(arr[-1,-10:])    

上面代码的输出(w/a0=5000):

First 10 Elements in First Row:
Virtual dataset:
[0 1 2 3 4 5 6 7 8 9]
Reading vdata into Array:
[0 1 2 3 4 5 6 7 8 9]
Last 10 Elements of Last Row:
Virtual dataset:
[5089 5090 5091 5092 5093 5094 5095 5096 5097 5098]
Reading vdata into Array:
[5089 5090 5091 5092 5093 5094 5095 5096 5097 5098]

0
投票

接受的答案确认这应该有效,但OP观察到它不起作用,因此这是一个需要报告的错误。

在这个答案中,我想提供有关此问题的更多信息以及解决此问题的建设性方法。


问题描述:

“虚拟”HDF5 数据集由几个较小的 HDF5 数据集组成。加载虚拟数据集时,有时可以观察到加载的“最后一个条目”实际上是“空”(即它们包含默认值,例如零、空字符串...)。至关重要的是,这种情况总是发生在加载文件的末尾 但是,当我们分别检查各个 HDF5 文件时,我们确实观察到

它们实际上不为空

按照

here

的建议将环境变量

HDF5_USE_FILE_LOCKING
设置为
FALSE
,但没有帮助。

问题说明:

Thomas Kluyver 在此论坛条目中清楚地解释了该问题:

https://forum.hdfgroup.org/t/virtual-dataset-in-read-write-file-missing-data-from-read-only-file /5647

操作系统限制单个进程可以同时打开的最大文件数。在 Linux 中,可以通过
    ulimit -Hn
  1. 检查,通常类似于
    1024
    当我们打开虚拟HDF5数据集时,进程会不断打开子文件,每个子文件都算作1个。
  2. 当超过限制时,HDF5 会默默忽略这一点,并且虚拟数据集中的相应条目将填充默认值(即“空数据”)。因此,我们将观察到,在某个时刻之后,我们的虚拟数据集具有空值,但子文件不为空。
解决方案/解决方法:

看来,如果我们计划聚合非常大量的文件,这个问题将持续存在,并且

它无法通过库或编程语言来修复,因为它源于操作系统

。具有管理员权限的用户也许能够扩展允许的文件数量,但这在最需要 HDF5 的计算集群中通常是不允许的,而且在我看来,将此数字设置为更大的常量无论如何都是一颗定时炸弹。 因此,解决方案似乎是摆脱虚拟结构,并将所有子文件聚合到一个主 HDF5 数据库中。

我将尝试在接下来的几天内上传

h5py

脚本并更新此答案以供参考。


讨论:

请注意,虚拟结构非常方便,因为我们可能希望多个并发进程同时写入数据库,而当我们有一个集中式文件时,这通常是不可能或不鼓励的。

但是一旦编写完成,如果虚拟结构包含>>100个文件,似乎将其转换为集中式是确保我们能够从lib/语言方面规避操作系统限制的唯一方法。

我很乐意犯错,所以如果有人有更好的想法,请分享! 干杯

安德烈斯


© www.soinside.com 2019 - 2024. All rights reserved.