Я начал использовать библиотеку multiprocessing.shared_memory
, как описано в документации .
То есть я создаю массив numpy
и записываю его в объект SharedMemory
одним process:
import multiprocessing.managers
import numpy
a = numpy.array([1, 2, 3, 4, 5, 6])
smm = multiprocessing.managers.SharedMemoryManager()
smm.start()
sm = smm.SharedMemory(size=a.nbytes)
b = numpy.ndarray(a.shape, dtype=a.dtype, buffer=sm.buf)
b[:] = a[:]
print(sm.name)
psm_ad5d71e1
И в другом процессе я ссылаюсь на SharedMemory
, используя его имя, и обращаюсь к массиву numpy таким образом:
import multiprocessing.shared_memory
import numpy
sm = multiprocessing.shared_memory.SharedMemory(name="psm_ad5d71e1")
c = numpy.ndarray((6,), dtype=numpy.int64, buffer=sm.buf)
print(c)
[1 2 3 4 5 6]
Пока все хорошо. Но в моем примере, когда массив numpy
становится намного больше (размер в ГБ), интерпретатор продолжает умирать (поскольку он просто завершает работу, не выбрасывая никаких исключений), когда я разыменовываю массив numpy
, созданный из объекта SharedMemory
, то есть, линия print(c)
.
После долгого эксперимента я понял, что если я ссылаюсь на прямую MemoryObject
, все работает, как ожидалось:
import multiprocessing.managers
import numpy
import pickle
a = numpy.array([1, 2, 3, 4, 5, 6])
smm = multiprocessing.managers.SharedMemoryManager()
smm.start()
sm = smm.SharedMemory(size=a.nbytes)
b = numpy.ndarray(a.shape, dtype=a.dtype, buffer=sm.buf)
b[:] = a[:]
with open('sm.pcl', 'wb') as f:
pickle.dump(sm, f)
И в других вместо этого я делаю это:
import multiprocessing.shared_memory
import numpy
import pickle
with open('sm.pcl', 'rb') as f:
sm = pickle.load(f)
c = numpy.ndarray((6,), dtype=numpy.int64, buffer=sm.buf)
print(c)
[1 2 3 4 5 6]
(В моем реальном примере я не pickle
SharedMemory
объект вручную, это делается автоматически, когда я передаю объект SharedMemory
в аргументах в отдельный процесс.)
Так что мой вопрос просто, это безопасно? Или я использую библиотеку непреднамеренным (и небезопасным) способом?
Если бы я догадался, это должно быть безопасно, поскольку объект SharedMemory
сам по себе является указателем. Поэтому я считаю, что это должно быть то же самое, что ссылаться на сам объект SharedMemory
или ссылаться на него через атрибут name
, используя функцию SharedMemory
...
Но я бы хотел, чтобы кто-то кто на самом деле знает комментарий! Заранее спасибо!