前言
multiprocessing.shared_memory 模块是 Python3.8 引入的新功能,目的是为了多进程编程提供共享内存功能,该模块主要包含两个类 SharedMemory 与 SharebleList, 后者在前者的基础之上进一步进行了封装。同时为了管理共享内存,在multiprocessing.managers定义了SharedMemoryManager, 进一步封装SharedMemory 与 SharebleList。
SharedMemory(name=None, create=False, size=0)
创建或者加载一个共享内存,create参数为True时,表示创建一个新的共享内存块,为False时,需要与name参数搭配使用,name参数值赋值为一个已经存在的共享内存块标识名。name参数用于标识共享内存块,为字符串,size参数指定共享内存的字节大小。
内存共享的目标是为了提高多进程通信的效率,因此在实践中,应该在每一进程中初始化一个SharedMemory实例对象,这些对象应该指向同一共享内存块。另外某些子进程可能会早于其它进程结束,因此在进程退出时,应该调用该进程内的
SharedMemory实例对象的close()方法——切断SharedMemory实例对象与共享内存块的连接。当所有进程都不在需要访问共享内存时,应该在最后一个退出进程中调用SharedMemory实例对象的unlink()方法——回收共享内存块。
如何访问或者修改共享内存的内容呢?通过SharedMemory实例对象的buf属性,该属性返回一个memoryview实例对象。buf的操作支持字节形式。
import multiprocessing as mp
from multiprocessing.shared_memory import SharedMemory, ShareableList
def f(name):
shm_child = SharedMemory(name=name, create=False)
shm_child.buf[:10] = bytearray(list(range(10, 0, -1)))
shm_child.close()
return
if __name__ == "__main__":
shm_main = SharedMemory(create=True, size=10) # size 是指字节数
shm_main.buf[:] = bytearray(list(range(10))) # 只能通过字节的方式进行操作
for _ in shm_main.buf:
print(_, end=", ") # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
print()
p = mp.Process(target=f, args=(shm_main.name,))
p.start()
p.join()
for _ in shm_main.buf:
print(_, end=", ") # 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
shm_main.close()
shm_main.unlink()
ShareableList(sequence=None, *, name=None)
ShareableList 实例管理的共享数据依然存储在 SharedMemory 实例中,ShareableList 实例对象的shm属性返回的就是 SharedMemory 实例。SharedMemory 访问值或者修改值,只能都过buf属性以字节形式进行操作,不大方便。而 ShareableList 实例支持存储值为“字符串、浮点型、整数型、布尔型、None”数据类型,但注意 ShareableList 实例的长度不可变更,并且不支持切片新建 ShareableList 实例对象。
在初始化时,如果 sequence 参数值不为空,则传递的实参会存储到共享内存块。如果 sequence 参数值为空,则 name 参数值必须为一个已存在的 SharedMemory.name。 最后 ShareableList 实例对象释放共享内存资源依然是通过 SharedMemory 实例对象。
def f(ls):
ls[1] = 99
ls[2] += 99
ls.shm.close()
return
if __name__ == "__main__":
x = ShareableList([1, 2, 3])
print(x) # ShareableList([1, 2, 3], name='wnsm_8ff28f7b')
p = mp.Process(target=f, args=(x,))
p.start()
p.join()
for _ in range(len(x)):
print(x[_], end=", ") # 1, 99, 102
x.shm.close()
x.shm.unlink()
multiprocessing.managers.SharedMemoryManager
封装了 SharedMemory 与 SharebleList,使用 SharedMemoryManager 实例管理创建共享内存与释放共享内存。
import multiprocessing as mp
from multiprocessing.managers import SharedMemoryManager
def f(ls, s, e):
for idx in range(s, e):
ls[idx - s] = ls[e - 1 - idx]
return
if __name__ == "__main__":
with SharedMemoryManager() as smm:
x = smm.ShareableList(list(range(10)))
p = mp.Process(target=f, args=(x, 0, len(x)))
p.start()
p.join()
for _ in x:
print(_, end=", ")