9.3 多进程
由于GIL,一个基于线程的Python程序永远只能一次使用一个处理器的时间。写本地Python程序做并发处理时,这样很让人焦急。历史上,人们使用过一些临时的解决方案,比如开多个Python进程,通过文件系统进行通信等。
从版本2.6开始,Python包含了一个入门级的并发处理模块multiprocessing。它以类似线程的方式管理多个Python进程。
HDF5也可以使用multiprocessing,不过需要记住一些注意事项。最重要的是记住新进程继承了来自父进程的HDF5库的状态。一种很常见的情况是多个进程为了一个打开的文件互相竞争。在本书写作时(2013年8月),这种情况甚至会发生在只读的文件上,这跟multiprocessing的实现细节有关,它的实现基于Linux/Unix操作系统的fork()系统调用。HDF组织已经意识到了这个限制,你可以检查h5py/PyTables的最新文档看看该限制是否已经被解决了。
同时,为了避免问题,这里有一些预防手段:
1.仅在主进程里进行文件I/O,且不要在文件打开时使用multiprocessing功能。
2.多个子进程可以安全地读取同一个文件;但文件必须在新进程创建以后打开。
3.让每个子进程写入不同的文件,在结束时合并它们。
图9-2显示了流程(1)。初始的进程负责文件I/O,并通过queue以及其他multiprocessing组件跟子进程通信。
图9-2 基于multiprocessing的HDF5程序概览
有一种Python并发计算的一种机制叫“进程池”,它将工作任务分派给工作进程。进程池是multiprocessing.Pool的实例,它具有一个内建的map()可以将工作并行分派:
下面是一个HDF5使用Pool的例子。假设我们有一个文件包含一个1维数据集,内含坐标对,我们想要计算它们到原点的距离。这对于并发计算来说是小菜一碟,因为每次计算都不会互相依赖。首先创建文件,它包含一个“coords”数据集:
我们的程序会用一个仅一条语句的函数计算距离,一个拥有4个工作进程的进程池来处理1 000次运算。注意当我们调用map时没有打开任何文件:
如果你想要用multiprocessing和HDF5干更复杂的活,事情就复杂了。你的进程不能同时访问同一个文件。要么你像上面那样在主进程显式进行I/O,要么你让每个进程生成一堆较小的“碎片”文件,然后在结束时将它们连结在一起:
这段代码简直令人崩溃,主要就是因为多个进程会为打开的文件竞争。有没有一种方法能够在进程间共享一个文件,并自动对读写进行同步?答案是:并发HDF5。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论