【发布时间】:2017-10-08 21:18:35
【问题描述】:
我有一个巨大的 hdf5 文件(~100GB,连续存储),我需要随机访问不同的点。在 python/h5py 或 C/H5Dread 中使用索引似乎很慢,因此我想直接映射数据。
事实上,这在我的本地 64 位 Fedora 25 上的 h5py/numpy 中有效,遵循this。但是在远程集群上,numpy/mmap 对大文件 ([Errno 12] Cannot allocate memory) 失败,即使 python 似乎是 64 位并且在 C 中使用 mmap 对 100GB 文件进行简单测试也可以。所以我集群的 Python 可能有问题。
我看到的一个解决方案是在 C 中使用 mmap。我写了一个小的 test 来创建一个带有一维数据集的小型 hdf5,并使用“H5Dget_offset”获取数据集偏移量。但是,结果并不正确。
以下是核心代码:
/* Get dataset offset within file */
file_id = H5Fopen (FILE, H5F_ACC_RDONLY, H5P_DEFAULT);
dataset_id = H5Dopen2(file_id, "/dset", H5P_DEFAULT);
offset = H5Dget_offset(dataset_id);
fd = open(FILE, O_RDONLY);
// align with page size
pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
length = NX * NY * sizeof(int);
addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
MAP_PRIVATE, fd, pa_offset);
blog 下的讨论提到了 Julia 中通过H5Fget_vfd_handle 和H5Dget_offset 实现这一点的实现,但我没有找到详细/简单的解释。
- 我通过 python/h5py 的
dataset.id.get_offset获得的偏移量与我通过 C 中的H5Dget_offset获得的偏移量相同。 - 我认为我的核心问题是:如何使用 C 的
H5Dget_offset给出的偏移量来映射数据集。 - 首先,
mmap是否应该比单纯的 hdf5 访问快得多?
【问题讨论】:
-
为什么内存映射而不是仅仅寻找和阅读?
-
@tadman ,“寻找和阅读”是指直接索引吗?我试过了,但速度很慢。我不知道索引是否会产生一些额外的开销?对我来说,每次只随机访问一个数据点,不断循环,而不是切片,这是hdf5使用的典型情况。
-
如果您在unbuffered mode 中打开文件,那么您可以直接、原始、低级别地访问该文件。使用
fseek/fread,您可以从任意位置获取数据,随机访问。默认情况下,文件读取是缓冲的,这可能会拖累性能,除非您进行线性读取。 -
谢谢@tadman。我将尝试无缓冲模式。但是,我觉得我的问题是从
H5Dget_offset返回的偏移量并不完全是从我通过open打开的文件头到实际数据空间开头的偏移量(代码中的文件描述符fd) .也许这个偏移量必须与H5Fget_vfd_handle返回的地址一起使用,但是我还没有弄清楚如何使用该地址(如我所见,这是文件描述符的一些地址)。无论如何,使用fseek/fread仍然需要正确的偏移量。 -
我不确定该文件中发生了什么,但可能存在不应计入偏移量的标题或某些框架。在许多二进制文件格式中,存在维护自己独立偏移量的嵌套结构。