当前位置: 首页 > news >正文

python SharedMemory

# 聊聊Python里的SharedMemory

最近在项目里用到了Python的multiprocessing.shared_memory模块,感觉这东西挺有意思的。平时大家写多进程程序,进程间通信是个绕不开的话题,而共享内存算是其中比较直接的一种方式。

他是什么

简单来说,SharedMemory就是一块内存区域,多个Python进程都能访问这块内存。想象一下,你有个白板放在办公室中间,所有人都能在上面写字、擦除、修改内容。这个白板就是共享内存,每个员工就是一个进程。

不过要注意的是,这个“白板”不是智能白板,它不会自动同步内容。如果两个人同时往同一个位置写字,最后写的内容会覆盖之前的内容。这既是共享内存的优势(速度快),也是需要小心的地方。

在Python 3.8之前,要实现类似的功能得用multiprocessing.Array或者multiprocessing.Value,但那些用起来总感觉有点绕。SharedMemory出现后,事情变得直接多了。

他能做什么

最典型的场景就是需要多个进程处理同一批数据,而且数据量比较大。比如说,你有个几GB的图像数据需要处理,如果用队列或者管道在进程间传递,光是复制数据就要花不少时间。用共享内存的话,数据只存在一份,各个进程直接去读去写,省去了复制开销。

另一个场景是进程间需要频繁交换数据。比如实时数据处理系统,一个进程负责采集数据,其他进程负责分析、存储、转发。如果每个数据包都通过IPC机制传递,延迟可能会比较高。用共享内存做中间缓冲区,效率会好很多。

还有些情况是进程间需要共享状态。虽然Python有multiprocessing.Manager可以创建共享对象,但那些对象通常是通过代理访问的,性能不如直接操作内存。对于需要高性能状态共享的场景,共享内存是个不错的选择。

怎么使用

用起来其实挺简单的。先创建一个共享内存块,给它起个名字,指定大小。其他进程通过这个名字就能找到这块内存,然后像操作普通字节数组一样操作它。

frommultiprocessingimportshared_memoryimportnumpyasnp# 创建共享内存shm=shared_memory.SharedMemory(create=True,size=1024)print(f"共享内存名字:{shm.name}")# 写入数据buffer=shm.bufbuffer[0:10]=b'Hello World'# 在另一个进程中(或者同一个进程的另一处)existing_shm=shared_memory.SharedMemory(name=shm.name)print(existing_shm.buf[0:10].tobytes())# 输出: b'Hello World'# 用完后记得关闭和清理existing_shm.close()shm.close()shm.unlink()

实际项目中,经常会把共享内存和numpy数组结合起来用。因为很多数据处理都是数值计算,用numpy方便很多。

# 创建共享内存并包装成numpy数组shm=shared_memory.SharedMemory(create=True,size=1000)array=np.ndarray((250,),dtype=np.float32,buffer=shm.buf)# 填充数据array[:]=np.random.randn(250)# 其他进程可以这样访问existing_shm=shared_memory.SharedMemory(name=shm.name)same_array=np.ndarray((250,),dtype=np.float32,buffer=existing_shm.buf)

这里有个细节要注意:所有进程对数据类型的理解必须一致。如果创建时用的是float32,其他进程也必须用float32来解读,否则数据就乱套了。

最佳实践

用了段时间后,总结出几个经验。

首先是内存管理。共享内存创建后不会自动释放,必须显式调用unlink()。这有点像文件操作,创建了文件得记得删除。比较好的做法是用try-finally或者上下文管理器确保资源被正确清理。

classSharedMemoryContext:def__init__(self,name=None,size=0):self.shm=shared_memory.SharedMemory(create=True,name=name,size=size)def__enter__(self):returnself.shmdef__exit__(self,exc_type,exc_val,exc_tb):self.shm.close()self.shm.unlink()

其次是并发控制。共享内存本身不提供锁机制,如果多个进程同时写同一块内存,数据可能会损坏。需要根据实际情况加锁,可以用multiprocessing.Lock,但要注意锁的粒度。锁得太细,性能受影响;锁得太粗,并发效果不好。

数据对齐也是个需要注意的点。特别是和C扩展库交互时,如果共享内存要传递给C函数,可能需要考虑内存对齐问题。Python层面不太明显,但跨语言时就会暴露出来。

还有个实践是给共享内存起有意义的名字。系统重启后,共享内存名字可能被重用,如果程序崩溃后重启,可能会连接到错误的内存块。可以在名字里加入进程ID、时间戳等信息,减少冲突概率。

和同类技术对比

Python里进程间通信的方式不少,各有各的适用场景。

multiprocessing.Queue是最常用的,用起来简单,线程安全,但数据需要序列化反序列化,对于大数据量性能开销大。适合传递消息、命令这种小数据。

multiprocessing.Pipe和队列类似,但更轻量,不过同样有序列化开销。

multiprocessing.Manager可以创建共享对象,比如列表、字典,用起来像本地对象,但所有操作都通过代理,性能一般。适合共享配置、状态这种不需要频繁操作的数据。

mmap模块也能实现共享内存,而且更底层,跨平台兼容性好。但mmap通常需要文件系统支持,而SharedMemory可以在纯内存中操作。如果不需要持久化,SharedMemory更简洁。

和这些技术相比,SharedMemory的优势很明显:速度快,没有序列化开销,内存使用效率高。但缺点也很明显:需要自己处理并发,数据类型要手动管理,出错时调试比较困难。

选择哪种技术,得看具体需求。如果数据量大、对性能要求高、进程生命周期相同,共享内存是个好选择。如果只是传递简单消息,或者需要跨机器通信,那还是用队列、管道更合适。

最后说点个人感受。共享内存这种技术,用好了能大幅提升性能,用不好就是调试的噩梦。它给了开发者很大的自由度,也带来了相应的责任。在决定使用之前,最好先评估下是否真的需要,有没有更简单的方案。很多时候,简单的方案虽然性能差一点,但维护成本低,长期来看更划算。

技术选型就是这样,没有绝对的好坏,只有适合不适合。共享内存是个好工具,但要知道什么时候用它,怎么用好它。

http://www.jsqmd.com/news/592539/

相关文章:

  • **时序数据库实战:用InfluxDB构建高吞吐物联网数据采集系统**在现代物联网(IoT)场
  • FlycoTabLayout:构建Android沉浸式导航体验的高效解决方案
  • 基于COMSOL相场法与水平集方法的多孔介质两相驱替模拟案例与随机孔隙度几何程序定制
  • 哪些任务永远不应该交给Agent
  • 如何让ollama-for-amd释放AMD GPU潜能?完整落地指南
  • 5分钟快速上手:QtScrcpy安卓投屏与虚拟按键终极指南
  • ORACLE数据库星型模型设计实例
  • 20251909 2024-2025-2 《网络攻防实践》实验三
  • 硬件工程师避坑指南:从选型到焊接,搞定晶振不起振的10个实战细节
  • 项目管理系统项目模板权限模板报表模板怎么做才能快速复制
  • 2025届必备的十大AI学术神器实际效果
  • BiliTools哔哩哔哩工具箱2026年:跨平台资源管理终极解决方案与完整指南
  • 百考通:精准匹配当前主流技术方向与行业需求,让研究更顺畅
  • 2026届必备的AI辅助论文神器实测分析
  • [特殊字符]C/C++内存管理深度解剖:从内存布局到new/delete底层,吃透面试必考核心
  • Emby高级功能终极解锁指南:免费获得完整Premiere体验的完整教程
  • 我受够了要给不同的Agent喂信息了
  • 拆解 OpenHands(14)--- Microagents
  • Synology Photos人脸识别功能突破全解析:跨设备适配与性能优化指南
  • [特殊字符]C++模板初阶通关:泛型编程核心,告别冗余代码!
  • WechatRealFriends:微信单向好友智能检测与关系管理工具
  • 探索Ryujinx:在PC上免费畅玩Switch游戏的完整指南
  • 从CAD到Web地图:LibreDWG解析DWG的坑我都帮你踩完了(Python实战)
  • AGV 自动充电是什么
  • Windows Defender Control深度解析:开源Windows Defender管理工具完全指南
  • Xilinx DDR4与DDR3多通道读写防冲突设计:高效稳定,支持最高8通道并行操作
  • 百考通:AI精准赋能,让研究更顺畅
  • LRCGet:三步解决离线音乐库歌词同步难题的终极免费工具
  • Visual C++运行库终极修复指南:一劳永逸解决DLL缺失问题
  • GeoServer实战:如何用MBTiles扩展包发布高德/谷歌多层级地图(含WPS扩展配置)