【问题标题】:h5py In-Memory File and Multiprocessing Errorh5py 内存中文件和多处理错误
【发布时间】:2013-02-13 13:22:41
【问题描述】:

这是给你的 HDF5 多处理专家...首先,我知道 python h5py 和多处理模块不一定彼此喜欢,但我收到一个错误,我就是想不通。我正在处理的脚本创建一个临时 in-memory hdf5 文件,将来自(pickle)输入文件的数据存储在内存文件中,然后执行多处理池(只读)对临时 HDF5 文件中的数据进行操作。

我已经能够隔离导致错误的代码,所以这里有一个简化的代码 sn-p。当我在生成器函数中创建 in-memory hdf5 文件,然后使用该生成器为多处理池生成参数时,我得到了一系列 HDF5 错误。这里有一些代码,我可以尽可能简单地重新创建错误:

import h5py
from multiprocessing import Pool
from itertools import imap

useMP = True

def doNothing(arg):
    print "Do nothing with %s"%arg

def myGenerator():
    print "Create hdf5 in-memory file..."
    hdfFile = h5py.File('test.hdf',driver='core',backing_store=False)
    print "Finished creating hdf5 in-memory file."
    yield 3.14159
    '''
    # uncommenting this section will result in yet another HDF5 error.
    print "Closing hdf5 in-memory file..."
    hdfFile.close()
    print "Finished closing hdf5 in-memory file."
    '''

if useMP:
    pool = Pool(1)
    mapFunc = pool.imap
else:
    mapFunc = imap

data = [d for d in mapFunc(doNothing,myGenerator())]

当我使用 itertools.imap(设置“useMP=False”)时,如预期的那样,我得到以下输出:

Create hdf5 in-memory file...
Finished creating hdf5 in-memory file.
Do nothing with 0

但是当我使用 Pool.imap 时,即使池仅使用单个工作线程创建,我也会得到以下输出:

Create hdf5 in-memory file...
HDF5-DIAG: Error detected in HDF5 (1.8.9) thread 139951680009984:
  #000: ../../../src/H5F.c line 1538 in H5Fopen(): unable to open file
    major: File accessability
    minor: Unable to open file
  #001: ../../../src/H5F.c line 1227 in H5F_open(): unable to open file: time = Wed Feb 27 09:32:32 2013
, name = 'test.hdf', tent_flags = 1
    major: File accessability
    minor: Unable to open file
  #002: ../../../src/H5FD.c line 1101 in H5FD_open(): open failed
    major: Virtual File Layer
    minor: Unable to initialize object
  #003: ../../../src/H5FDcore.c line 464 in H5FD_core_open(): unable to open file
    major: File accessability
    minor: Unable to open file
Finished creating hdf5 in-memory file.
Do nothing with 0

奇怪的是,这个错误不会导致程序崩溃。我正在编写的导致此错误的脚本实际上按我的预期工作 - 但它为它创建的每个内存文件提供了上述错误。使用 itertools.imap 时没有错误,读取现有 HDF5 文件时没有错误,只有多处理和内存中 HDF5 文件的组合。

h5py 版本 2.1.1

hdf5 版本 1.8.9

Python 2.7.3 版

【问题讨论】:

    标签: python multiprocessing hdf5 in-memory h5py


    【解决方案1】:

    在挖掘了一些 h5py 文件之后,我找到了一个部分答案,但仍然不完整。 h5py.File 类在h5py/_hl/files.py 中定义。在调用make_fid()的File对象创建过程中出现错误:

    def make_fid(name, mode, userblock_size, fapl):
        """ Get a new FileID by opening or creating a file.
        Also validates mode argument."""
        ...
        elif mode == 'a' or mode is None:
            try:
                fid = h5f.open(name, h5f.ACC_RDWR, fapl=fapl)
                try:
                    existing_fcpl = fid.get_create_plist()
                    if userblock_size is not None and existing_fcpl.get_userblock() != userblock_size:
                        raise ValueError("Requested userblock size (%d) does not match that of existing file (%d)" % (userblock_size, existing_fcpl.get_userblock()))
                except:
                    fid.close()
                    raise
            except IOError:
                fid = h5f.create(name, h5f.ACC_EXCL, fapl=fapl, fcpl=fcpl)
    

    如果文件存在,则以读/写模式打开。如果它不存在(内存文件就是这种情况),则 h5f.open() 调用会引发异常。正是这个对 h5f.open 的调用触发了 H5Fopen() 错误消息。

    仍然悬而未决的问题是为什么仅在使用多处理时才打印错误?首先,我假设创建 HDF5 文件的生成器函数被主线程调用。好吧,事实并非如此。多处理池实际上创建了一个新线程来处理 imap 和 imap_unordered 的任务,但不用于 map/map_async。将pool.imap替换为pool.map,从主线程调用生成器函数,不打印错误信息。那么为什么在单独的线程中创建 HDF5 文件会引发错误呢?

    -------- 更新 -----------

    显然,h5py 会自动在主线程中使 HDF5 错误消息静音,因为 h5py 会处理错误。但是,它还不会自动使子线程中的错误静音。解决方案:h5py._errors.silence_errors()。此函数禁用当前线程中的自动 HDF5 错误打印。请参阅 h5py issue 206。此代码消除 HDF5 错误:

    import h5py
    from multiprocessing import Pool
    from itertools import imap
    import threading
    
    useMP = True
    
    def doNothing(arg):
        print "Do nothing with %s"%arg
    
    def myGenerator():
        h5py._errors.silence_errors()
        print "Create hdf5 in-memory file..."
        hdfFile = h5py.File('test.hdf',driver='core',backing_store=False)
        print "Finished creating hdf5 in-memory file."
        yield 3.14159
    
    if useMP:
        pool = Pool(1)
        mapFunc = pool.map
    else:
        mapFunc = imap
    
    data = [d for d in mapFunc(doNothing,myGenerator())]
    

    【讨论】:

    猜你喜欢
    • 2014-10-15
    • 2017-07-15
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 2012-10-27
    • 2011-10-11
    • 1970-01-01
    相关资源
    最近更新 更多