通过shared_memory实现的对象数据共享,属于更加底层的接口操作,使用起来还要首先进行数据类型的映射,还有没有别的方式能够实现对象数据的共享呢,这就引出了今天的主角Manager。
需要说明的是,Manager从使用层面上看,似乎简化了共享内存的操作,提供了更高级别的封装、简化。但是,其本质上与共享内存是完全不同的。
本文的主要内容有:
1、Manager模块概述
2、Manager的使用演示
3、Manager的底层实现及与共享内存的区别
Manager模块概述multiprocessing.Manager模块是Python中用于进程间进行对象数据共享的工具。它提供了支持多进程共享数据的一种方式,允许多个进程之间通过代理(proxy)的方式访问共享对象。
通过Manager模块,可以轻松创建出各种类型的共享对象,比如列表、字典、队列等,省去了使用共享内存还需要手动进行数据类型映射内存区域的麻烦。
Manager模块主要提供了以下几种功能:
1、创建共享的数据结构:Manager模块可以创建共享的列表、字典、队列等数据结构,使得多个进程可以安全地访问和修改这些数据结构。
2、支持多进程同步:Manager模块中也提供了类似于多线程中的锁(Lock)、信号量(Semaphore)等同步原语,以帮助管理并发访问共享数据的情况。
3、简化进程间通信:通过使用Manager模块,可以简化地进行进程间通信,避免使用低层次的共享内存或者其他IPC机制。
Manager的使用演示接下来通过代码来简单演示一下通过Manager进行对象数据共享的方式。
直接看代码:
运行结果:
从上述代码中关于Manager模块的使用,似乎是简化了的共享内存一样,代码很直观、易读。关于Manager的使用,可以参考以下步骤:
1、创建Manager对象
2、通过Manager对象的各种方法进行需要共享对象的数据结构,比如list()、dict()等。
3、在子进程中访问这些对象数据结构,即可实现跨进程的对象数据的共享。
Manager的底层实现及与共享内存的区别从编码层面上来看,通过使用Manager的方式实现的对象数据共享,比较类似共享内存的方式,而且是更加简化的共享内存的方式。
但是,实际上两者在底层实现上存在很大的差别。
关于共享内存的方式,我们在上一篇文章中已经提及,这里简单回顾一下:
共享内存是一种更加底层的方式,直接操作内存区域,省去了进行对象数据的序列化、传输、反序列化的各种操作,避免了数据的复制,所以从性能来说,这种方式是最优的。但是,需要对底层共享内存区域进行数据结构的映射,比如通过Numpy中的ndarray,才能更加方便使用。所以,在编码操作上会略显繁琐。
而Mananger在底层实现上,其实还是与Pipe和Queue更加类似。关于Manager的底层实现,这里简单进行几点说明:
1、Manager本质上是通过创建一个服务器进程来进行共享对象的管理,所有创建的共享对象(字典、列表等)都是通过一个代理对象与这个管理进程进行交互。这些共享对象实际上是在管理进程的地址空间中,而不是在创建它们的主进程或者子进程中。
2、主进程和子进程实质上是通过网络套接字(Socket)的方式与管理进程进行通信,这种通信方式使得管理进程能够接收操作请求并返回结果。
3、由于进程通信方式是通过网络实现,所以,所有的共享对象在发送和接收时都需要进行序列化(内部默认是使用Python的pickle模块)。在进行通信时,首先进行序列化,转换为字节流进行网络传输,在接收方再进行反序列化操作。
所以,相关的序列化、通信环节带来的性能开销是与Pipe和Queue类似的,如果业务需求上存在性能的要求,还是应该首先选择共享内存的方式。
总的来说,Manager是一种在使用方式上更像共享内存,但是在底层实现上更像Pipe、Queue的进程间通信机制。
总结本文简单介绍了Manager模块的使用,并简单提及了关于Manager模块的底层实现细节。最后,对比了共享内存的使用,给出结论,“Manger是一种用起来像共享内存,底层实现上像Queue和Pipe的IPC机制”。
以上就是本文的全部内容,感谢您的拨冗阅读!