如何在异步上下文中读取(hdf5)文件?

Posted

技术标签:

【中文标题】如何在异步上下文中读取(hdf5)文件?【英文标题】:How to read from (hdf5) file in async contexts? 【发布时间】:2019-05-02 12:27:24 【问题描述】:

最近我一直在玩一些 Python 3 的异步功能。总的来说,我对 3.6 语法很满意,当然还有你获得的性能提升。在我看来,围绕ASGI 标准发展的令人兴奋的项目之一是starlette。我有一个示例应用程序正在运行,我正在从hdf5 文件中读取数据。 h5py 还不支持异步 I/O。这给我留下了一个问题:我在这里所做的一切有意义吗?据我了解,这段代码毕竟是同步运行的。在异步上下文中执行 I/O 的推荐方法是什么?

async def _flow(indexes):
    print('received flow indexes %s ' %indexes)
    # uses h5py under the hood
    gr = GridH5ResultAdmin(gridadmin_f, results_f)
    t = gr.nodes.timeseries(indexes=indexes)
    data = t.only('s1').data
    # data is a numpy array
    return data['s1'].tolist()

@app.route('/flow_velocity')
async def flow_results(request):

    indexes_list = [[2,3,4,5], [6,7,8,9], [10,11,12,13]]

    tasks = []
    loop = asyncio.get_event_loop()
    t0 = datetime.datetime.now()
    for indexes in indexes_list:
        print('Start getting indexes %s' % indexes)
        # Launch a coroutine for each data fetch
        task = loop.create_task(_flow(indexes))
        tasks.append(task)

    # Wait on, and then gather, all data
    flow_data = await asyncio.gather(*tasks)
    dt = (datetime.datetime.now() - t0).total_seconds()
    print('elapsed time:  [s]'.format(dt))

    return JSONResponse('flow_velocity': flow_data)

日志记录:

INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
Start getting indexes "[2, 3, 4, 5]"
Start getting indexes "[6, 7, 8, 9]"
Start getting indexes "[10, 11, 12, 13]"
received flow indexes [2, 3, 4, 5] 
received flow indexes [6, 7, 8, 9] 
received flow indexes [10, 11, 12, 13]
elapsed time: 1.49779 [s]

【问题讨论】:

【参考方案1】:

不幸的是h5py 模块你不能使用asyncio,你在这里做的主要是顺序的,因为如果 I/O 部分不能异步完成,那么你的异步代码的其余部分没有太多意义了

https://github.com/h5py/h5py/issues/837

该线程的摘要

所以添加异步支持有两个不同的问题:

    asyncio 目前明确不支持文件系统 I/O,参见例如https://github.com/python/asyncio/wiki/ThirdParty#filesystem、https://groups.google.com/forum/#!topic/python-tulip/MvpkQeetWZA、What is the status of POSIX asynchronous I/O (AIO)? 和 https://github.com/Tinche/aiofiles,这是最接近您想要的。 所有 I/O 都通过 HDF5(库)完成,因此无论您想添加什么异步支持都需要 HDF5(库)中的支持

这基本上意味着 h5py 不太可能支持 asyncio。

您可以尝试在线程中运行东西,但不能保证它会正常工作,正如我所提到的,HDF5 控制 I/O,并且您需要确保不会遇到它的任何锁定控制。您可能想了解http://docs.h5py.org/en/latest/high/file.html#file-drivers 中提到的哪种文件模式最适合您。也许您可以考虑其他替代方案,例如 multiprocessing 或 concurrent.futures?

【讨论】:

你可以将 h5py 一个 python 类文件对象传递给 h5py,然后在类文件对象级别实现 asyncio(实现读、写、截断等),我有一个例子的工作(付出了很多努力),但我想我可能遇到了你在这里提到的 h5 锁定机制,因为事情似乎几乎是按顺序运行的,尽管在类文件对象上使用原始 .read() 调用的相同代码运行得非常好快速 - 从本地集群 S3 接口使用 asyncio(带 20 个事件循环实例)进行 1.5 GB/秒的随机搜索。 HDF5 领域在异步 I/O 方面取得了一些进展:hdf5-vol-async.readthedocs.io/en/latest,但我知道没有 python 绑定。

以上是关于如何在异步上下文中读取(hdf5)文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C++ 中的 hdf5 文件中读取数据块?

如何使用 C++ API 在 HDF5 文件中写入/读取锯齿状数组?

如何从 HDF5 文件中读取属性?

如何使用 h5py 读取只有数据集(无组)的 HDF5 文件?

如何读取 hdf5 文件。并将它们绘制为图像

如何读取 .hdf5 数据文件作为卷积神经网络的输入?