multiprocessing.shared_memory — Предоставляет общую память для прямого доступа между процессами
Исходный код: Lib/multiprocessing/shared_memory.py
Введено в версии 3.8.
Этот модуль предоставляет класс SharedMemory для выделения и управления общей памятью, к которой могут обращаться один или несколько процессов на многоядерной или симметричной многопроцессорной (SMP) машине. Для помощи в управлении жизненным циклом общей памяти, особенно между различными процессами, также предоставляется подкласс BaseManager, SharedMemoryManager, в модуле multiprocessing.managers.
В данном модуле общая память относится к блокам общей памяти «стиля System V» (хотя она не обязательно реализуется явно как таковая) и не относится к «распределенной общей памяти». Этот стиль общей памяти позволяет различным процессам потенциально читать и записывать в общую (или разделяемую) область динамической памяти. Процессы обычно ограничены доступом только к своему собственному пространству памяти процесса, но общая память позволяет обмениваться данными между процессами, избегая необходимости отправлять сообщения между процессами, содержащими эти данные. Прямая передача данных через память может обеспечить значительные преимущества производительности по сравнению с передачей данных через диск или сокет или другие средства связи, требующие сериализации/десериализации и копирования данных.
-
Создаёт новый блок общей памяти или подключается к существующему блоку общей памяти. Каждому блоку общей памяти присваивается уникальное имя. Таким образом, один процесс может создать блок общей памяти с определённым именем, а другой процесс может подключиться к этому же блоку общей памяти, используя то же имя.
В качестве ресурса для обмена данными между процессами, блоки общей памяти могут существовать дольше, чем исходный процесс, который их создал. Когда одному процессу больше не нужен доступ к блоку общей памяти, который всё ещё может потребоваться другим процессам, необходимо вызвать метод
close(). Когда блоком общей памяти больше не пользуется ни один процесс, необходимо вызвать методunlink(), чтобы обеспечить надлежащую очистку.name — уникальное имя запрошенной общей памяти, заданное как строка. При создании нового блока общей памяти, если используется
None(по умолчанию), будет сгенерировано новое имя.create управляет тем, создаётся ли новый блок общей памяти (
True) или подключается существующий (False).size указывает запрашиваемое количество байтов при создании нового блока общей памяти. Поскольку некоторые платформы выбирают выделение блоков памяти на основе размера страницы памяти данной платформы, точный размер блока общей памяти может быть больше или равен запрошенному размеру. При подключении к существующему блоку общей памяти параметр
sizeигнорируется.-
Закрывает доступ к общей памяти из этого экземпляра. Для обеспечения надлежащей очистки ресурсов все экземпляры должны вызвать
close()после того, как экземпляр больше не нужен. Обратите внимание, что вызовclose()не приводит к уничтожению самого блока общей памяти.
-
Запрашивает уничтожение базового блока общей памяти. Для обеспечения надлежащей очистки ресурсов
unlink()следует вызвать один раз (и только один раз) во всех процессах, которым нужен блок общей памяти. После запроса уничтожения блок общей памяти может быть или не быть немедленно уничтожен, и это поведение может отличаться на разных платформах. Попытки доступа к данным внутри блока общей памяти после того, какunlink()был вызван, могут привести к ошибкам доступа к памяти. Примечание: последний процесс, освобождающий свой доступ к блоку общей памяти, может вызватьunlink()иclose()в любом порядке.
-
Объект memoryview содержимого блока общей памяти.
-
Только для чтения уникальное имя блока общей памяти.
-
Только для чтения размер блока общей памяти в байтах.
-
Следующий пример демонстрирует низкоуровневое использование экземпляров 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 массивами, доступ к одному и тому же numpy.ndarray из двух разных оболочек Python:
>>> # 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
-
Подкласс
BaseManager, который можно использовать для управления блоками общей памяти между процессами.Вызов
start()на экземпляреSharedMemoryManagerзапускает новый процесс. Цель этого нового процесса — управлять жизненным циклом всех блоков общей памяти, созданных через него. Чтобы инициировать освобождение всех блоков общей памяти, управляемых этим процессом, вызовитеshutdown()на экземпляре. Это вызоветSharedMemory.unlink()на всех объектахSharedMemory, управляемых этим процессом, а затем остановит сам процесс. Создавая экземплярыSharedMemoryчерезSharedMemoryManager, мы избегаем необходимости вручную отслеживать и вызывать освобождение ресурсов общей памяти.Этот класс предоставляет методы для создания и возвращения экземпляров
SharedMemoryи для создания подобного списку объекта (ShareableList) на основе общей памяти.Обратитесь к
multiprocessing.managers.BaseManagerза описанием наследования address и authkey необязательных входных аргументов и о том, как их можно использовать для подключения к уже существующей службеSharedMemoryManagerиз других процессов.-
Создаёт и возвращает новый объект
SharedMemoryс указанным размеромsizeв байтах.
-
Создаёт и возвращает новый объект
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
При использовании объекта SharedMemoryManager в операторе with, все блоки общей памяти, созданные с помощью этого менеджера, освобождаются, когда блок кода оператора with завершается.
-
Предоставляет изменяемый список, подобный объекту, где все хранящиеся значения хранятся в блоке общей памяти. Это ограничивает сохраняемые значения только
int,float,bool,str(менее 10 МБ каждый),bytes(менее 10 МБ каждый) иNoneвстроенными типами данных. Также он существенно отличается от встроенного типаlistтем, что эти списки не могут изменять свою общую длину (т.е. нет добавления, вставки и т.д.) и не поддерживают динамическое создание новыхShareableListэкземпляров с помощью срезов.sequence используется для заполнения нового
ShareableListзначениями. Установлено наNoneдля подключения к уже существующемуShareableListпо его уникальному имени общей памяти.name — уникальное имя запрошенной общей памяти, как описано в определении
SharedMemory. При подключении к существующемуShareableList, укажите уникальное имя блока общей памяти, оставивsequenceравнымNone.-
Возвращает количество вхождений
value.
-
Возвращает позицию первого индекса
value. ВызываетValueError, еслиvalueотсутствует.
-
Только для чтения атрибут, содержащий формат упаковки
struct, используемый всеми значениями, хранящимися в данный момент.
-
Экземпляр
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()
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.9/library/multiprocessing.shared_memory.html