Python 多进程共享内存:multiprocessing.shared_memory
模块详解
在 Python 中,multiprocessing
模块提供了多进程支持,而多进程编程中,经常会遇到需要多个进程共享数据的需求。为了避免进程之间的高昂数据传输成本,可以使用共享内存机制。在 Python 3.8 版本及之后,multiprocessing.shared_memory
模块提供了更高效的共享内存操作,使得不同进程可以访问同一块内存区域而无需复制数据。
本文将详细介绍 multiprocessing.shared_memory
模块的使用方法,并通过示例展示如何实现多进程之间的共享内存。
1. 什么是共享内存?
共享内存是一种进程间通信(IPC)方式,多个进程可以直接访问一块共享的内存区域。在 Python 中,multiprocessing.shared_memory
模块允许多个进程共享同一内存块,避免了进程间数据传输的复制开销。
在 Python 3.8 之前,multiprocessing
中的共享内存是通过 Value
和 Array
等方式实现的,而 multiprocessing.shared_memory
提供了一种更为高效且灵活的共享内存机制。
2. multiprocessing.shared_memory
模块简介
multiprocessing.shared_memory
模块允许不同进程访问同一块内存区域,具体提供了以下关键类:
- SharedMemory:这是主要的类,表示一块共享内存区域。你可以通过它创建共享内存、访问共享内存、传递共享内存给其他进程等。
- ShareableList:这是一个可以在多进程之间共享的列表,内部分配在共享内存中。
3. 如何使用 multiprocessing.shared_memory
3.1 创建和访问共享内存
要使用共享内存,首先需要通过 SharedMemory
类创建一块共享内存,然后可以通过索引方式访问内存中的数据。
示例:创建共享内存并在多个进程中使用
import multiprocessing
from multiprocessing import shared_memory
import numpy as np
def modify_shared_memory(shm_name):
# 连接到已经存在的共享内存
existing_shm = shared_memory.SharedMemory(name=shm_name)
# 将共享内存转换为 NumPy 数组
np_array = np.ndarray((4,), dtype=np.int64, buffer=existing_shm.buf)
# 修改共享内存中的数据
for i in range(len(np_array)):
np_array[i] *= 2
print("Child Process Modified Data:", np_array)
def main():
# 创建一块共享内存区域,大小为 4 * 8 字节(4 个 int64 类型的元素)
shm = shared_memory.SharedMemory(create=True, size=4 * 8)
# 将共享内存转换为 NumPy 数组
np_array = np.ndarray((4,), dtype=np.int64, buffer=shm.buf)
# 初始化数据
np_array[:] = [1, 2, 3, 4]
print("Initial Data in Parent Process:", np_array)
# 创建并启动子进程
p = multiprocessing.Process(target=modify_shared_memory, args=(shm.name,))
p.start()
p.join()
# 子进程修改后的共享内存数据
print("Data in Parent Process After Child Modification:", np_array)
# 清理共享内存
shm.close()
shm.unlink()
if __name__ == "__main__":
main()
代码解析:
- 在
main
函数中,通过shared_memory.SharedMemory(create=True, size=4 * 8)
创建一块大小为 4 * 8 字节的共享内存。这块内存会存储 4 个int64
类型的数据。 - 然后,将这块共享内存转换为一个
numpy
数组,方便进行数据操作。 - 在父进程中,初始化共享内存数据为
[1, 2, 3, 4]
,然后启动一个子进程。 - 子进程通过
shared_memory.SharedMemory(name=shm_name)
获取共享内存的引用,并通过numpy
数组访问并修改共享内存中的数据。 - 最后,父进程打印出修改后的数据,证明共享内存中的数据是可以被多个进程共享和修改的。
输出:
Initial Data in Parent Process: [1 2 3 4]
Child Process Modified Data: [2 4 6 8]
Data in Parent Process After Child Modification: [2 4 6 8]
3.2 共享内存的清理
使用完共享内存后,应该调用 shm.close()
来关闭共享内存,并调用 shm.unlink()
来解除共享内存的连接。
4. 高级用法:ShareableList 和 ShareableDict
除了直接使用 SharedMemory
,multiprocessing.shared_memory
还提供了两种高层次的封装,ShareableList
和 ShareableDict
,它们分别提供了多进程共享列表和字典的功能。
4.1 使用 ShareableList
ShareableList
是一个支持多进程共享的列表,它会将数据存储在共享内存中。
from multiprocessing import shared_memory
def modify_shared_list(shm_name):
# 连接到现有的共享内存
existing_shm = shared_memory.ShareableList(name=shm_name)
# 修改共享列表中的数据
existing_shm[0] = 99
print("Child Process Modified Data:", existing_shm)
def main():
# 创建一个支持多进程共享的列表
shared_list = shared_memory.ShareableList([1, 2, 3, 4])
print("Initial Data in Parent Process:", shared_list)
# 启动子进程修改共享列表
p = multiprocessing.Process(target=modify_shared_list, args=(shared_list.name,))
p.start()
p.join()
print("Data in Parent Process After Child Modification:", shared_list)
# 清理共享内存
shared_list.shm.close()
shared_list.shm.unlink()
if __name__ == "__main__":
main()
输出:
Initial Data in Parent Process: [1, 2, 3, 4]
Child Process Modified Data: [99, 2, 3, 4]
Data in Parent Process After Child Modification: [99, 2, 3, 4]
4.2 使用 ShareableDict
ShareableDict
是一个可以在多个进程之间共享的字典。
from multiprocessing import shared_memory
def modify_shared_dict(shm_name):
# 连接到现有的共享字典
existing_shm = shared_memory.ShareableDict(name=shm_name)
# 修改共享字典中的数据
existing_shm['key1'] = 'value1'
print("Child Process Modified Data:", existing_shm)
def main():
# 创建一个支持多进程共享的字典
shared_dict = shared_memory.ShareableDict({'key': 'initial_value'})
print("Initial Data in Parent Process:", shared_dict)
# 启动子进程修改共享字典
p = multiprocessing.Process(target=modify_shared_dict, args=(shared_dict.name,))
p.start()
p.join()
print("Data in Parent Process After Child Modification:", shared_dict)
# 清理共享内存
shared_dict.shm.close()
shared_dict.shm.unlink()
if __name__ == "__main__":
main()
输出:
Initial Data in Parent Process: {'key': 'initial_value'}
Child Process Modified Data: {'key': 'initial_value', 'key1': 'value1'}
Data in Parent Process After Child Modification: {'key': 'initial_value', 'key1': 'value1'}
5. 总结
multiprocessing.shared_memory
模块使得多个进程可以直接访问共享内存,提高了多进程间数据共享的效率,避免了传统进程间通信方式(如管道、队列)的数据复制开销。- 使用
SharedMemory
类可以创建共享内存,而ShareableList
和ShareableDict
类提供了对共享列表和字典的高层次封装。 - 共享内存的清理非常重要,使用完毕后需要调用
shm.close()
和shm.unlink()
来释放资源。
通过这种方式,可以更高效地在多进程中进行数据共享,尤其适用于需要频繁访问和修改共享数据的场景。
发表回复