​multiprocessing.shared_memory --- 可跨进程直接访问的共享内存​

news2024/5/19 9:15:07

源代码: Lib/multiprocessing/shared_memory.py

3.8 新版功能.


该模块提供了一个 SharedMemory 类,用于分配和管理多核或对称多处理器(SMP)机器上进程间的共享内存。为了协助管理不同进程间的共享内存生命周期,multiprocessing.managers 模块也提供了一个 BaseManager 的子类: SharedMemoryManager

本模块中,共享内存是指 "System V 类型" 的共享内存块(虽然可能和它实现方式不完全一致)而不是 “分布式共享内存”。这种类型的的共享内存允许不同进程读写一片公共(或者共享)的易失性存储区域。一般来说,进程被限制只能访问属于自己进程空间的内存,但是共享内存允许跨进程共享数据,从而避免通过进程间发送消息的形式传递数据。相比通过磁盘、套接字或者其他要求序列化、反序列化和复制数据的共享形式,直接通过内存共享数据拥有更出色性能。

class multiprocessing.shared_memory.SharedMemory(name=Nonecreate=Falsesize=0)

创建一个新的共享内存块或者连接到一片已经存在的共享内存块。每个共享内存块都被指定了一个全局唯一的名称。通过这种方式,进程可以使用一个特定的名字创建共享内存区块,然后其他进程使用同样的名字连接到这个共享内存块。

作为一种跨进程共享数据的方式,共享内存块的寿命可能超过创建它的原始进程。一个共享内存块可能同时被多个进程使用,当一个进程不再需要访问这个共享内存块的时候,应该调用 close() 方法。当一个共享内存块不被任何进程使用的时候,应该调用 unlink() 方法以执行必要的清理。

name 是共享内存的唯一名称,字符串类型。如果创建一个新共享内存块的时候,名称指定为 None (默认值),将会随机产生一个新名称。

create 指定创建一个新的共享内存块 (True) 还是连接到已存在的共享内存块 (False) 。

如果是新创建共享内存块则 size 用于指定块的大小为多少字节。由于某些平台是以内存页大小为最小单位来分配内存的,最终得到的内存块大小可能大于或等于要求的大小。如果是连接到已经存在的共享内存块, size 参数会被忽略。

close()

关闭实例对于共享内存的访问连接。所有实例确认自己不再需要使用共享内存的时候都应该调用 close() ,以保证必要的资源清理。调用 close() 并不会销毁共享内存区域。

unlink()

请求销毁底层的共享内存块。 为了执行必要的资源清理,在所有使用这个共享内存块的进程中,unlink() 应该调用一次(且只能调用一次)。 发出此销毁请求后,共享内存块可能会、也可能不会立即销毁,且此行为在不同操作系统之间可能不同。 调用 unlink() 后再尝试访问其中的数据可能导致内存错误。 注意:最后一个关闭共享内存访问权限的进程可以以任意顺序调用 unlink() 和 close()。

buf

共享内存块内容的 memoryview 。

name

共享内存块的唯一标识,只读属性。

size

共享内存块的字节大小,只读属性。

以下示例展示了 SharedMemory 底层的用法:

>>>

>>> from multiprocessing import shared_memory
>>> shm_a = shared_memory.SharedMemory(create=True, size=10)
>>> type(shm_a.buf)
<class 'memoryview'>
>>> buffer = shm_a.buf
>>> len(buffer)
10
>>> buffer[:4] = bytearray([22, 33, 44, 55])  # Modify multiple at once
>>> buffer[4] = 100                           # Modify single byte at a time
>>> # Attach to an existing shared memory block
>>> shm_b = shared_memory.SharedMemory(shm_a.name)
>>> import array
>>> array.array('b', shm_b.buf[:5])  # Copy the data into a new array.array
array('b', [22, 33, 44, 55, 100])
>>> shm_b.buf[:5] = b'howdy'  # Modify via shm_b using bytes
>>> bytes(shm_a.buf[:5])      # Access via shm_a
b'howdy'
>>> shm_b.close()   # Close each SharedMemory instance
>>> shm_a.close()
>>> shm_a.unlink()  # Call unlink only once to release the shared memory

下面的例子展示了 SharedMemory 类结合 NumPy 数组 的实际应用,从两个独立的 Python shell 访问同一个 numpy.ndarray:

>>>

>>> # In the first Python interactive shell
>>> import numpy as np
>>> a = np.array([1, 1, 2, 3, 5, 8])  # Start with an existing NumPy array
>>> from multiprocessing import shared_memory
>>> shm = shared_memory.SharedMemory(create=True, size=a.nbytes)
>>> # Now create a NumPy array backed by shared memory
>>> b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
>>> b[:] = a[:]  # Copy the original data into shared memory
>>> b
array([1, 1, 2, 3, 5, 8])
>>> type(b)
<class 'numpy.ndarray'>
>>> type(a)
<class 'numpy.ndarray'>
>>> shm.name  # We did not specify a name so one was chosen for us
'psm_21467_46075'

>>> # In either the same shell or a new Python shell on the same machine
>>> import numpy as np
>>> from multiprocessing import shared_memory
>>> # Attach to the existing shared memory block
>>> existing_shm = shared_memory.SharedMemory(name='psm_21467_46075')
>>> # Note that a.shape is (6,) and a.dtype is np.int64 in this example
>>> c = np.ndarray((6,), dtype=np.int64, buffer=existing_shm.buf)
>>> c
array([1, 1, 2, 3, 5, 8])
>>> c[-1] = 888
>>> c
array([  1,   1,   2,   3,   5, 888])

>>> # Back in the first Python interactive shell, b reflects this change
>>> b
array([  1,   1,   2,   3,   5, 888])

>>> # Clean up from within the second Python shell
>>> del c  # Unnecessary; merely emphasizing the array is no longer used
>>> existing_shm.close()

>>> # Clean up from within the first Python shell
>>> del b  # Unnecessary; merely emphasizing the array is no longer used
>>> shm.close()
>>> shm.unlink()  # Free and release the shared memory block at the very end

class multiprocessing.managers.SharedMemoryManager([address[, authkey]])

BaseManager 的子类,可用于管理跨进程的共享内存块。

调用 SharedMemoryManager 实例上的 start() 方法会启动一个新进程。这个新进程的唯一目的就是管理所有由它创建的共享内存块的生命周期。想要释放此进程管理的所有共享内存块,可以调用实例的 shutdown() 方法。这会触发执行它管理的所有 SharedMemory 对象的 SharedMemory.unlink() 方法,然后停止这个进程。通过 SharedMemoryManager 创建 SharedMemory 实例,我们可以避免手动跟踪和释放共享内存资源。

这个类提供了创建和返回 SharedMemory 实例的方法,以及以共享内存为基础创建一个列表类对象 (ShareableList) 的方法。

有关继承的可选输入参数 address 和 authkey 以及他们如何用于从进程连接已经存在的 SharedMemoryManager 服务,参见 multiprocessing.managers.BaseManager 。

SharedMemory(size)

使用 size 参数,创建一个新的指定字节大小的 SharedMemory 对象并返回。

ShareableList(sequence)

创建并返回一个新的 ShareableList 对象,通过输入参数 sequence 初始化。

下面的案例展示了 SharedMemoryManager 的基本机制:

>>>

>>> from multiprocessing.managers import SharedMemoryManager
>>> smm = SharedMemoryManager()
>>> smm.start()  # Start the process that manages the shared memory blocks
>>> sl = smm.ShareableList(range(4))
>>> sl
ShareableList([0, 1, 2, 3], name='psm_6572_7512')
>>> raw_shm = smm.SharedMemory(size=128)
>>> another_sl = smm.ShareableList('alpha')
>>> another_sl
ShareableList(['a', 'l', 'p', 'h', 'a'], name='psm_6572_12221')
>>> smm.shutdown()  # Calls unlink() on sl, raw_shm, and another_sl

以下案例展示了 SharedMemoryManager 对象的一种可能更方便的使用方式,通过 with 语句来保证所有共享内存块在使用完后被释放。

>>>

>>> with SharedMemoryManager() as smm:
...     sl = smm.ShareableList(range(2000))
...     # Divide the work among two processes, storing partial results in sl
...     p1 = Process(target=do_work, args=(sl, 0, 1000))
...     p2 = Process(target=do_work, args=(sl, 1000, 2000))
...     p1.start()
...     p2.start()  # A multiprocessing.Pool might be more efficient
...     p1.join()
...     p2.join()   # Wait for all work to complete in both processes
...     total_result = sum(sl)  # Consolidate the partial results now in sl

在 with 语句中使用 SharedMemoryManager  对象的时候,使用这个管理器创建的共享内存块会在 with 语句代码块结束后被释放。

class multiprocessing.shared_memory.ShareableList(sequence=None\*name=None)

提供了一个类似于可变列表的对象,其中存储的所有值都存储在一个共享内存块中。 这限制了可存储的值只能是 int (带符号的 64 位), floatboolstr (当以 utf-8 编码时每个值小于 10M 字节), bytes (每个值小于 10M 字节) 和 None 内置数据类型。 它与 list 内置类型的另一个显著区别在于这些列表不能改变其总长度 (例如不能追加、插入等),也不支持通过切片动态创建新的 ShareableList 实例。

sequence 会被用来为一个新的 ShareableList 填充值。 设为 None 则会基于唯一的共享内存名称关联到已经存在的 ShareableList

name 是所请求的共享内存的唯一名称,与 SharedMemory 的定义中所描述的一致。 当关联到现有的 ShareableList 时,则指明其共享内存块的唯一名称并将 sequence 设为 None

备注

bytes 和 str 值存在一个已知问题。 如果这些值以 \x00 空字节或字符结尾,那么在按索引从 ShareableList 抓取这些值时它们可能会被 静默地截去。 这种 .rstrip(b'\x00') 行为被认为是一个错误并可能在未来消失。 参见 gh-106939。

对于某些应用来说在右侧截去尾部空值会造成问题,要绕过此问题可以在存储这样的值时总是无条件地在其末尾附加一个额外的非 0 字节并在获取时无条件地移除它:

>>>

>>> from multiprocessing import shared_memory
>>> nul_bug_demo = shared_memory.ShareableList(['?\x00', b'\x03\x02\x01\x00\x00\x00'])
>>> nul_bug_demo[0]
'?'
>>> nul_bug_demo[1]
b'\x03\x02\x01'
>>> nul_bug_demo.shm.unlink()
>>> padded = shared_memory.ShareableList(['?\x00\x07', b'\x03\x02\x01\x00\x00\x00\x07'])
>>> padded[0][:-1]
'?\x00'
>>> padded[1][:-1]
b'\x03\x02\x01\x00\x00\x00'
>>> padded.shm.unlink()

count(value)

返回 value 出现的次数。

index(value)

返回 value 首次出现的位置,如果 value 不存在, 则抛出 ValueError 异常。

format

包含由所有当前存储值所使用的 struct 打包格式的只读属性。

shm

存储了值的 SharedMemory 实例。

下面的例子演示了 ShareableList 实例的基本用法:

>>>

>>> from multiprocessing import shared_memory
>>> a = shared_memory.ShareableList(['howdy', b'HoWdY', -273.154, 100, None, True, 42])
>>> [ type(entry) for entry in a ]
[<class 'str'>, <class 'bytes'>, <class 'float'>, <class 'int'>, <class 'NoneType'>, <class 'bool'>, <class 'int'>]
>>> a[2]
-273.154
>>> a[2] = -78.5
>>> a[2]
-78.5
>>> a[2] = 'dry ice'  # Changing data types is supported as well
>>> a[2]
'dry ice'
>>> a[2] = 'larger than previously allocated storage space'
Traceback (most recent call last):
  ...
ValueError: exceeds available storage for existing str
>>> a[2]
'dry ice'
>>> len(a)
7
>>> a.index(42)
6
>>> a.count(b'howdy')
0
>>> a.count(b'HoWdY')
1
>>> a.shm.close()
>>> a.shm.unlink()
>>> del a  # Use of a ShareableList after call to unlink() is unsupported

下面的例子演示了一个、两个或多个进程如何通过提供下层的共享内存块名称来访问同一个 ShareableList:

>>>

>>> b = shared_memory.ShareableList(range(5))         # In a first process
>>> c = shared_memory.ShareableList(name=b.shm.name)  # In a second process
>>> c
ShareableList([0, 1, 2, 3, 4], name='...')
>>> c[-1] = -999
>>> b[-1]
-999
>>> b.shm.close()
>>> c.shm.close()
>>> c.shm.unlink()

下面的例子显示 ShareableList (以及下层的 SharedMemory) 对象可以在必要时被封存和解封。 请注意,它将仍然为同一个共享对象。 出现这种情况是因为被反序列化的对象具有相同的唯一名称并使用这个相同的名称附加到现有的对象上(如果对象仍然保持存活):

>>>

>>> import pickle
>>> from multiprocessing import shared_memory
>>> sl = shared_memory.ShareableList(range(10))
>>> list(sl)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>>

>>> deserialized_sl = pickle.loads(pickle.dumps(sl))
>>> list(deserialized_sl)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>>

>>> sl[0] = -1
>>> deserialized_sl[1] = -2
>>> list(sl)
[-1, -2, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(deserialized_sl)
[-1, -2, 2, 3, 4, 5, 6, 7, 8, 9]

>>>

>>> sl.shm.close()
>>> sl.shm.unlink()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法:有效的括号(入栈出栈)

时间复杂度 O(n) 空间复杂度 O(n∣Σ∣)&#xff0c;其中 Σ 表示字符集&#xff0c;本题中字符串只包含 6 种括号 /*** param {string} s* return {boolean}*/ var isValid function(s) {const map {"(":")","{":"}","["…

vue3若依框架,在页面中点击新增按钮跳转到新的页面,不是弹框,如何实现

在router文件中的动态路由数组中新增一个路由配置&#xff0c;这个配置的就是新的页面。 注意path不要和菜单配置中的路径一样&#xff0c;会不显示内容。 在菜单配置中要写权限标识就是permissions:[]里的内容 在children里的path要写占位符info/:data 点击新增按钮&#x…

初级数据结构(三)——栈

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 初级数据结构&#xff08;二&#xff09;——链表 | 初级数据结构&#xff08;四&#xff09;——队列 下一篇-> 1、栈的特性 1.1、函数栈帧简述 即使是刚入门几天的小白&#xff0c;对栈这个字…

一文读懂NISQ时代的量子竞赛

/目录/ 一、关于NISQ&#xff0c;业内专家怎么看&#xff1f; 二、NISQ时代的量子硬件资源估算 2.1. NISQ量子比特要求 2.2. NISQ计算时间 2.3. NISQ代码经典模拟 三、主流量子算法“优势”的资源估算 3.1. 用于化学模拟的VQE算法 3.2. 用于组合优化的QAOA算法 3.3. 量…

你真的了解Shiro框架吗?

关注公众号回复20231110获取最新网络安全以及内网渗透等资料。 文章目录 关注公众号回复20231110获取最新网络安全以及内网渗透等资料。Shiro的核心架构Shiro中的认证认证shiro中认证的关键对象 认证流程调试认证流程Shiro的加密过程Shiro中的解密过程总结 Shiro的核心架构 Shi…

低代码开发与传统软件开发:未来趋势与竞争格局

近年来&#xff0c;低代码开发平台的快速发展引起了各行各业的广泛关注。低代码开发平台简化了软件开发的复杂性&#xff0c;提供了更快速、更灵活的开发方式。于是&#xff0c;许多人开始产生一个疑问&#xff1a;未来低代码开发是否会取代传统软件开发&#xff1f;今天这篇文…

验收支撑-软件项目验收计划书

软件项目验收计划的作用主要有以下几点&#xff1a; 确保项目质量&#xff1a;通过项目验收&#xff0c;客户或相关方可以对项目的成果进行全面、系统的评估&#xff0c;以确保项目达到预期的质量标准。发现和解决问题&#xff1a;在项目开发过程中&#xff0c;难免会存在一些问…

ROS-ROS运行管理-ROS元功能包

ROS是多进程(节点)的分布式框架&#xff0c;一个完整的ROS系统实现&#xff1a; 可能包含多台主机&#xff1b;每台主机上又有多个工作空间(workspace)&#xff1b;每个的工作空间中又包含多个功能包(package)&#xff1b;每个功能包又包含多个节点(Node)&#xff0c;不同的节…

(Nerf学习)GaussianEditor

论文链接 https://arxiv.org/pdf/2311.14521.pdf 原码链接 https://github.com/buaacyw/GaussianEditor 一、安装&#xff08;WIN失败&#xff0c;求解决方法&#xff09; 我使用的环境是&#xff1a;Win11 python3.8 CUDA11.8 显卡3060 1、克隆我们的存储库并创建 conda …

【INTEL(ALTERA)】Agilex7 FPGA Development Kit DK-DK-DEV-AGI027RBES 编程/烧录/烧写/下载步骤

DK-DEV-AGI027RBES 的编程步骤&#xff1a; 将 USB 电缆插入 USB 端口 J8&#xff08;使用 J10 时&#xff0c;DIPSWITCH SW5.3&#xff08;DK-DEV-AGI027RES 和 DK-DEV-AGI027R1BES&#xff09;和 SW8.3&#xff08;DK-DEV-AGI027RB 和 DK-DEV-AGI027-RA&#xff09;应关闭&a…

【动态规划】路径问题_不同路径_C++

题目链接&#xff1a;leetcode不同路径 目录 题目解析&#xff1a; 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目解析&#xff1a; 题目让我们求总共有多少条不同的路径可到达右下角&#xff1b; 由题可得&#xff1a; 机器人位于…

蚂蚁SEO实用的网络baidu蜘蛛有哪些

网络蜘蛛是一种用于从互联网上自动抓取信息的程序。它们根据给定的规则和指令&#xff0c;遍历网站上的页面&#xff0c;收集信息并将其存储在数据库中。网络蜘蛛在搜索引擎、数据挖掘、信息提取等领域有着广泛的应用。本文将介绍一种实用的网络蜘蛛&#xff0c;并探讨其实现原…

iOS加密CoreML模型

生成模型加密密钥 必须在Xcode的Preferences的Accounts页面登录Apple ID&#xff0c;才能在Xcode中生成模型加密密钥。 在Xcode中打开模型&#xff0c;单击Utilities选项卡&#xff0c;然后单击“Create Encryption Key”按钮。 从下拉菜单中选择当前App的Personal Team&…

【抽象责任链模式】实践优化

责任链模式 原文来自 ——> https://nageoffer.com/pages/51ffef/#%E8%B4%A3%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F &#xff08;小调整重点标注&#xff0c;我是菜鸡&#xff09; 1. 什么是责任链 责任链设计模式是一种行为型设计模式&#xff0c;其主要目的是解耦请求发送…

mongoAltas使用

创建项目 https://cloud.mongodb.com/v2#/org/6548f5a62d5ab00f5b67a61a/projects 部署数据库 选择厂商部署 更改数据库用户和密码 添加数据库可访问地址 添加连接信息到vscode MONGO_URLmongodbsrv://burnchi:burnchicluster0.ynoq32i.mongodb.net/Auth-Mongodb偶尔分享web开…

mysql的redolog、undo、binlog的作用

概览&#xff1a; MySQL三大日志包括&#xff1a;undolog&#xff0c;redo log&#xff0c;binlog&#xff0c;它们分别有以下作用&#xff1a; undolog&#xff1a;是Innodb存储引擎事务生成的日志。用于事务的回滚和MVCC&#xff0c;保证了事务的原子性。 redo log&#x…

H5页面生成工具源码

源码介绍 H5是基于Vue2.0开发的&#xff0c;通过拖拽的形式&#xff0c;生成页面的工具&#xff0c;类似易企秀、百度H5等工具。 H5特征&#xff1a; 1、编辑器 参考线 吸附线、组件对齐 拽改变组件形状 元素: 复制&#xff08;画布&#xff09; 元素: 删除&#xff08…

Fractal-Streets

title: Fractal Streets date: 2023-12-13 14:48:45 tags: 分形 categories: 算法进阶指南 题目大意 将原来的城市复制一遍放在原城市的上方&#xff0c;将原城市顺时针90放在原城市的左上方&#xff0c;将逆时针90后的城市放在原城市的左边&#xff0c;然后用道路将四部分链接…

美赛F奖经验分享,干货满满,快来查收!

2023年美赛结果出来之后&#xff0c;陆续有人给我发私信求经验&#xff0c;跟一些同学交流后我发现&#xff0c;很多人其实对美赛了解程度很少。我借此机会介绍一下美赛&#xff0c;并分享一下获奖经验。我的内容主要包括以下几个部分&#xff1a;美赛是什么、得奖分布、选题建…

AI全栈大模型工程师(二十六)如何选择 GPU 和云服务厂商

&#x1f4a1; 这节课会带给你 如何选择 GPU 和云服务厂商&#xff0c;追求最高性价比 如何部署自己 fine-tune 的模型&#xff0c;向业务提供高可用推理服务 如何控制内容安全&#xff0c;做好算法备案&#xff0c;确保合规 开始上课&#xff01; 硬件选型 当我们为模型训练及…