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

这篇具有很好参考价值的文章主要介绍了​multiprocessing.shared_memory --- 可跨进程直接访问的共享内存​。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

源代码: 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]

>>>文章来源地址https://www.toymoban.com/news/detail-755450.html

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

到了这里,关于​multiprocessing.shared_memory --- 可跨进程直接访问的共享内存​的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CUDA编程模型系列六(利用shared memory和统一内存优化矩阵乘)

    CUDA编程模型系列六(利用shared memory和统一内存优化矩阵乘) 本系列教程将介绍具体的CUDA编程代码的细节 CUDA编程模型系列六(利用shared memory和统一内存优化矩阵乘)

    2024年02月11日
    浏览(50)
  • PostgreSQL数据库动态共享内存管理器——Dynamic shared memory areas

    dsm.c提供的功能允许创建后端进程间共享的共享内存段。DSA利用多个DSM段提供共享内存heap;DSA可以利用已经存在的共享内存(DSM段)也可以创建额外的DSM段。和系统heap使用指针不同的是,DSA提供伪指针,可以转换为backend-local指针,但是该伪指针可以在后端进程之间共享,可

    2024年02月15日
    浏览(43)
  • Android Binder机制浅谈以及使用Binder进行跨进程通信的俩种方式(AIDL以及直接利用Binder的transact方法实现)

    Binder机制学习 ·为何新增Binder来作为主要的IPC方式 Android也是基于Linux内核,Linux现有的进程通信手段有管道/消息队列/共享内存/套接字/信号量。 既然有现有的IPC方式,为什么重新设计一套Binder机制呢? 主要是出于以上三个方面的考量: 2. binder是什么? 从进程间通信的角度

    2024年02月16日
    浏览(34)
  • ERROR:ORA-01034: ORACLE not availableORA-27101: shared memory realm does not exist

    解决方法一: ERROR: ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist 进程 ID: 0 会话 ID: 0 序列号: 0 因为这个小小的错误,折腾了我好几个小时,特记录如下。 上网搜索了下解决方案,如下: sqlplus \\\"sys/password as sysdba\\\" 连接成功,提示\\\"已连接到空闲例程\\\" SQL startup OR

    2024年02月04日
    浏览(47)
  • 第12课【DMA 直接数据访问】直接数据访问 效率 数据总线冲突 通道 仲裁器

    DMA(Direct Memory Access 直接内存访问)指的是STM32中的一个外设。它可以在无需CPU介入的情况下,实现外设和存储器之间或存储器与存储器之间的数据传输,这里的存储器指的是SRAM或者是Flash。在进行一些大批量的,或者是周期性重复的数据转移工作时,通常都会使用到DMA,这

    2024年02月08日
    浏览(28)
  • JeecgBoot Vue3 版本前端后端设置免登录-不登录直接访问页面-前端免登录直接访问

    jeecgboot Vue3 版本做出了巨大的更新,前端项目的变动最大,在使用的时候官网文档有的地方没有介绍,如果您想做官网,前台的项目,这个时候需要绕过登录,直接进入项目,这个时候需要一下的配置,即可实现对应的功能。 在学习编程的时候不光要和老师,教程一一的学习

    2024年02月10日
    浏览(45)
  • 【ARMv9 DSU-120 系列 4.2 -- Utility Bus 访问的 memory-mapped 寄存器详细介绍】

    请阅读 【Arm® DynamIQ™ Shared Unit-120 专栏 】 ARMv9架构中的DSU-120(DynamIQ™ Shared Unit-120)提供了一组Cluster系统控制寄存器,这些寄存器可以通过两种方式访问: 通过Utility Bus上的内存映射访问 :允许外部设备或核心之外的系统与DSU-120的控制寄存器进行交互。 通过核心的系统寄

    2024年04月29日
    浏览(36)
  • Springboot使用DataRest直接访问数据库

    Spring-boot-data-rest 直接将数据库资源映射成为Rest资源 说明 Spring Data REST是基于Spring Data的repository之上,可以把 repository 自动输出为REST资源, 目前支持Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j、Spring Data GemFire、Spring Data Cassandra的 repository 自动转换成REST服务。 注意是自动。

    2024年02月11日
    浏览(34)
  • Springboot项目启动后浏览器不能直接访问接口,而postman可以访问?

    在云服务器上部署springboot后端时,项目启动后浏览器不能直接访问接口,而postman可以访问。这是当时困扰了我大半天的小问题,在我打开防火墙和阿里云安全组之后还是没解决。然后在网上搜了很多很多资料,以为是浏览器访问权限或者是https什么证书问题,到头来通过简单

    2024年02月21日
    浏览(51)
  • 为什么直接使用IP地址无法访问网站

    在一些情况下,使用IP地址不能直接访问网站的原因主要有以下几种: 虚拟主机技术 现在很多网站采用虚拟主机技术,即在同一个服务器上托管多个不同的网站,这些网站共享同一个IP地址。此时,访问这些网站需要根据 HTTP 请求中的 Host 头信息来确定具体访问哪个网站,而

    2024年02月11日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包