前言
Python3.8中的multiprocessing模块提供了一个 SharedMemory 类,用于分配和管理多核或对称多处理器(SMP)机器上进程间的共享内存。为了协助管理不同进程间的共享内存生命周期,multiprocessing.managers 模块也提供了一个 BaseManager 的子类: SharedMemoryManager。
在multiprocessing模块中,共享内存是指 “System V 类型” 的共享内存块而不是 “分布式共享内存”。这种类型的的共享内存允许不同进程读写一片公共(或者共享)的易失性存储区域。一般来说,进程被限制只能访问属于自己进程空间的内存,但是共享内存允许跨进程共享数据,从而避免通过进程间发送消息的形式传递数据。与通过磁盘、套接字或者其他要求序列化、反序列化和复制数据的共享形式相比,直接通过内存共享数据拥有更出色的性能。
简而言之,Python3.8引入的共享内存特性可以很方便的用于多个进程访问同一块数据内容。
而在Python3.8前,例如Python3.7和3.6则不具有该特性。在某些情况下,我们使用的某些依赖不支持Python3.8,但是又需要用到Python3.8的共享内存特性,那么这个时候可以考虑将Python3.8的共享内存特性移植到Python3.7/3.6中。
步骤
注:以Python3.7环境为例。
1. 下载shared_numpy工程
从Github上下载shared_numpy工程,链接地址在此。
git clone https://github.com/TracelessLe/shared_numpy.git
2. 编译
进入shared_numpy
工程目录,执行 python setup.py build_ext --inplace
,会在./shared_numpy/shared_numpy/
目录下会生成_posixshmem.cpython-37m-x86_64-linux-gnu.so和其他文件。
3. 拷贝文件到指定目录
将shared_numpy
工程目录下的resource_tracker.py
脚本拷贝到你所安装的python目录multiprocessing子目录下(例如/root/conda/envs/env_sample/lib/python3.7/multiprocessing/
)。
将生成的 _posixshmem*.so
文件拷贝到你所安装的python目录lib-dynload子目录下,如:
cp ./shared_numpy/_posixshmem.cpython-37m-x86_64-linux-gnu.so ~/conda/envs/env_sample/lib/python3.7/lib-dynload
4. 拷贝文件夹到目标工程主路径下
拷贝shared_numpy子文件夹到你需要使用shared_memory特性的目标工程主路径下,如:
cp ./shared_numpy/shared_numpy/ ./your_project_home_directory
5. 使用
将原先在Python3.8环境中使用shared_memory的代码从from multiprocessing import shared_memory
改为 from shared_numpy import shared_memory
。Enjoy it !
#from multiprocessing import shared_memory
from shared_numpy import shared_memory
特别感谢
基本的shared_memory功能来自Github用户dillonalaird的工程(https://github.com/dillonalaird/shared_numpy),在此基础上加入了Python3.8中对共享内存信号量和内存使用的跟踪功能(resource_tracker.py
)。
参考资料
[1] multiprocessing.shared_memory — 可从进程直接访问的共享内存
[2] Github - TracelessLe - shared_numpy
[3] Github - dillonalaird - shared_numpy
[4] Github - cpython/Lib/multiprocessing/shared_memory.py
[5] Github - cpython/Lib/multiprocessing/resource_tracker.py
[6] POSIX Shared Memory