Я хотел бы использовать массив numpy в общей памяти для использования с модулем многопроцессорности. Сложность состоит в том, чтобы использовать его как массив numpy, а не только как массив ctypes.
from multiprocessing import Process, Array
import scipy
def f(a):
a[0] = -a[0]
if __name__ == '__main__':
# Create the array
N = int(10)
unshared_arr = scipy.rand(N)
arr = Array('d', unshared_arr)
print "Originally, the first two elements of arr = %s"%(arr[:2])
# Create, start, and finish the child processes
p = Process(target=f, args=(arr,))
p.start()
p.join()
# Printing out the changed values
print "Now, the first two elements of arr = %s"%arr[:2]
Это дает такой результат, как:
Originally, the first two elements of arr = [0.3518653236697369, 0.517794725524976]
Now, the first two elements of arr = [-0.3518653236697369, 0.517794725524976]
Доступ к массиву можно получить с помощью ctypes, например, arr[i]
имеет смысл. Однако это не массив numpy, и я не могу выполнять такие операции, как -1*arr
, или arr.sum()
. Я полагаю, что решением было бы преобразовать массив ctypes в массив numpy. Однако (помимо того, что я не могу выполнить эту работу), я не верю, что ею больше будут делиться.
Кажется, было бы стандартное решение того, что должно быть общей проблемой.
python
numpy
multiprocessing
shared
Ян Лэнгмор
источник
источник
subprocess
скорее спрашивает , чемmultiprocessing
.Ответы:
Чтобы добавить к ответам @ unutbu (больше не доступно) и @Henry Gomersall. Вы можете использовать
shared_arr.get_lock()
для синхронизации доступа при необходимости:пример
Если вам не нужен синхронизированный доступ или вы создаете свои собственные блокировки, в
mp.Array()
этом нет необходимости. Вы можете использоватьmp.sharedctypes.RawArray
в этом случае.источник
count
кnumpy.frombuffer()
. Вы можете попробовать сделать это на более низком уровне, используяmmap
или что-то вроде того,posix_ipc
чтобы реализовать изменяемый размер (может включать копирование при изменении размера) аналог RawArray (или искать существующую библиотеку). Или, если ваша задача позволяет: копировать данные по частям (если вам не нужно все сразу). «Как изменить размер разделяемой памяти» - хороший отдельный вопрос.Pool()
определяет количество процессов (по умолчанию используется количество доступных ядер процессора).M
- количество вызововf()
функции.С
Array
объектомget_obj()
связан метод, который возвращает массив ctypes, представляющий интерфейс буфера. Я думаю, что следующее должно работать ...При запуске, это выводит на первый элемент в
a
настоящее время 10.0, показываяa
иb
лишь два мнения в той же памяти.Для того , чтобы убедиться , что он по - прежнему многопроцессорных безопасности, я считаю , вы должны будете использовать
acquire
иrelease
методы , которые существуют наArray
объекте,a
и встроенный в замок , чтобы убедиться , что его все благополучно получить доступ (хотя я не эксперт на многопроцессорный модуль).источник
mp.Array
.Хотя уже даны хорошие ответы, существует гораздо более простое решение этой проблемы при соблюдении двух условий:
В этом случае вам не нужно возиться с явным созданием общих переменных, поскольку дочерние процессы будут созданы с помощью вилки. Разветвленный дочерний элемент автоматически разделяет пространство памяти родителя. В контексте многопроцессорной обработки Python это означает, что он разделяет все переменные уровня модуля ; обратите внимание, что это не относится к аргументам, которые вы явно передаете своим дочерним процессам, или к функциям, которые вы вызываете на каком-то
multiprocessing.Pool
или около того.Простой пример:
источник
Я написал небольшой модуль python, который использует разделяемую память POSIX для совместного использования массивов numpy между интерпретаторами python. Может быть, тебе это пригодится.
https://pypi.python.org/pypi/SharedArray
Вот как это работает:
источник
Вы можете использовать
sharedmem
модуль: https://bitbucket.org/cleemesser/numpy-sharedmemВот ваш исходный код, на этот раз с использованием общей памяти, которая ведет себя как массив NumPy (обратите внимание на дополнительный последний оператор, вызывающий функцию NumPy
sum()
):источник