如何加速从压缩的HDF5文件读取

问题描述 投票:-1回答:1

我有几个大的HDF5文件存储在SSD上(lzf压缩文件大小为10-15 GB,未压缩大小为20-25 GB)。将这样的文件中的内容读入RAM进行进一步处理每个文件大约需要2分钟。在此期间,仅使用一个核心(但是100%)。所以我想在CPU上运行的解压缩部分是瓶颈而不是SSD的IO吞吐量。

在我的程序开始时,它会将这种类型的多个文件读入RAM,这需要相当长的时间。我喜欢通过利用更多内核和最终更多内存来加速这一过程,直到SSD IO吞吐量成为限制因素。我正在研究的机器有足够的资源(20个CPU核心[+ 20 HT]和400 GB RAM)和“浪费”RAM并不是什么大问题,只要通过节省时间来证明这一点。

我自己有两个想法:

1)使用python的multiprocessing模块并行读取多个文件到RAM中。这原则上是有效的,但由于在multiprocessing中使用了Pickle(如here所述),我达到了4 GB的序列化限制:

OverflowError('无法序列化大于4 GiB的字节对象')。

2)制作几个进程(使用Pool模块中的multiprocessing)打开相同的HDF5文件(使用with h5py.File('foo.h5', 'r') as h_file:),从中读取一个单独的块(chunk = h_file['label'][i : i + chunk_size])并返回该块。然后将聚集的块连接起来。然而,这失败了

OSError:无法读取数据(Fletcher32校验和检测到数据错误)。

这是因为我在多个进程中打开了相同的文件(如here建议的那样)?


所以我的最后一个问题是:如何更快地将.h5文件的内容读入主内存?再次:»浪费«RAM有利于节省时间是允许的。内容必须驻留在主存储器中,因此通过读取行​​或分数来避免问题不是一种选择。我知道我可以只存储未压缩的.h5文件,但这只是我喜欢使用的最后一个选项,因为SSD上的空间很少。我更喜欢避风港,压缩文件和快速阅读(理想情况下通过更好地利用可用资源)。

元信息:我使用python 3.5.2和h5py 2.8.0。


编辑:在读取文件时,SSD的工作速度为72 MB / s,远远超过其最大值。 .h5文件是使用h5py的create_dataset方法和compression="lzf"选项创建的。

编辑2:这是(简化)我用来读取(压缩)HDF5文件内容的代码:

def opener(filename, label): # regular version
    with h5py.File(filename, 'r') as h_file:
        data = g_file[label][:]
    return data

def fast_opener(filename, label): # multiple processes version
    with h5py.File(filename, 'r') as h_file:
        length = len(h_file[label])
    pool = Pool() # multiprocessing.Pool and not multiprocessing.dummy.Pool
    args_iter = zip(
        range(0, length, 1000),
        repeat(filename),
        repeat(label),
    )
    chunks = pool.starmap(_read_chunk_at, args_iter)
    pool.close()
    pool.join()
    return np.concatenate(chunks)

def _read_chunk_at(index, filename, label):
    with h5py.File(filename, 'r') as h_file:
        data = h_file[label][index : index + 1000]
    return data

如您所见,解压缩是通过h5py透明地完成的。

python python-3.x hdf5 h5py
1个回答
1
投票

h5py通过过滤器处理LZF文件的解压缩。在C中实现的过滤器的源代码是available on the h5py Github here。看看implementation of lzf_decompress,它是导致你瓶颈的功能,你可以看到它没有并行化(不知道它是否可以并行化,我会把这个判断留给那些对LZF内部工作更熟悉的人)。

话虽如此,我担心没有办法只需要你的巨大压缩文件和多线程解压缩它。据我所知,您的选择是:

  • 将较大的文件拆分为较小的单独压缩块,并在单独的核心上并行解压缩每个块(multiprocessing可能有帮助,但您需要注意进程间共享内存)并在解压缩后将所有内容重新连接在一起。
  • 只需使用未压缩的文件。
© www.soinside.com 2019 - 2024. All rights reserved.