有没有一种方法可以使用POSIX_FADV_DONTNEED标志打开hdf5文件?

时间:2020-06-16 18:52:14

标签: python numpy ubuntu memory-management h5py

我们正在针对机器学习应用程序使用python中带有h5py的大型(1.2TB)未压缩,未分块的hdf5文件进行工作,这需要我们反复遍历整个数据集,并以随机顺序分别加载〜15MB的切片。我们正在使用具有192 GB RAM的Linux(Ubuntu 18.04)计算机。我们注意到该程序正在缓慢填充高速缓存。当高速缓存的总大小达到可与机器全部RAM相媲美的大小时(可用内存几乎排在前0,但有足够的“可用”内存)交换会减慢所有其他应用程序的速度。为了查明问题的根源,我们编写了一个单独的最小示例来隔离我们的数据加载过程-但发现问题与方法的每个部分无关。

我们尝试过: 构建numpy memmap并访问请求的切片:

#on init:
f = h5py.File(tv_path, 'r')
hdf5_event_data = f["event_data"]
self.event_data = np.memmap(tv_path, mode="r", shape=hdf5_event_data.shape,                                           
                            offset=hdf5_event_data.id.get_offset(),dtype=hdf5_event_data.dtype)
self.e = np.ones((512,40,40,19))

#on __getitem__:
self.e = self.event_data[index,:,:,:19]
return self.e

在每次调用getitem时重新打开memmap:

#on __getitem__:
self.event_data = np.memmap(self.path, mode="r", shape=self.shape,
                                            offset=self.offset, dtype=self.dtype)
self.e = self.event_data[index,:,:,:19]
return self.e

直接寻址h5文件并转换为numpy数组:

#on init:
f = h5py.File(tv_path, 'r')
hdf5_event_data = f["event_data"]
self.event_data = hdf5_event_data
self.e = np.ones((512,40,40,19))

#on __getitem__:
self.e = self.event_data[index,:,:,:19]
return self.e

我们还在pytorch Dataset / Dataloader框架中尝试了上述方法-但这没什么区别。

我们观察到/ proc / buddyinfo证明了高内存碎片。通过同步删除缓存; echo 3> / proc / sys / vm / drop_caches在应用程序运行时无济于事。在应用程序启动之前清理缓存将消除交换行为,直到缓存再次吞噬内存-并再次开始交换。

我们的工作假设是系统正在尝试保留高速缓存的文件数据,这会导致内存碎片。最终,即使大多数内存仍然“可用”,在请求新内存时也会进行交换。

这样,我们转向了围绕文件缓存更改Linux环境行为的方法,并找到了这篇文章。在python中打开h5文件或通过numpy memmap访问的一部分h5文件时,是否有一种方法可以调用POSIX_FADV_DONTNEED标志,这样就不会发生这种高速缓存的积累?在我们的用例中,我们不会长时间重新访问该文件的特定位置(直到我们访问文件的所有其他“片”)

1 个答案:

答案 0 :(得分:1)

您可以使用os.posix_fadvise来告诉OS如何使用计划加载的区域。自然,这需要一些低级调整才能确定您的文件描述符,并了解您计划读取的区域。

获取文件描述符的最简单方法是自己提供:

pf = open(tv_path, 'rb')
f = h5py.File(pf, 'r')

您现在可以设置建议。对于整个文件:

os.posix_fadvise(os.fileno(pf), 0, f.id.get_filesize(), os.POSIX_FADV_DONTNEED)

或对于特定数据集:

os.posix_fadvise(os.fileno(pf), hdf5_event_data.id.get_offset(),
                 hdf5_event_data.id.get_storage_size(), os.POSIX_FADV_DONTNEED)

其他要查看的东西

H5py做自己的chunk caching。您可能要尝试关闭此功能:

f = h5py.File(..., rdcc_nbytes=0)

作为替代方案,您可能希望尝试使用h5py中提供的其他drivers中的一个,例如'sec2'

f = h5py.File(..., driver='sec2')