Общая переменная в многопроцессорной обработке Python

Первый вопрос: в чем разница между Value и Manager().Value?

Во-вторых, возможно ли использовать целочисленную переменную без использования Value? Ниже приведен мой пример кода. То, что я хочу, это получить диктат со значением целое число, а не значение. То, что я сделал, это просто изменил все это после процесса. Есть ли более простой способ?

from multiprocessing import Process, Manager

def f(n):
    n.value += 1

if __name__ == '__main__':
    d = {}
    p = []

    for i in range(5):
        d[i] = Manager().Value('i',0)
        p.append(Process(target=f, args=(d[i],)))
        p[i].start()

    for q in p:
        q.join()

    for i in d:
        d[i] = d[i].value

    print d

1 ответ

Решение

Когда вы используете Value Вы получаете ctypes объект в разделяемой памяти, который по умолчанию синхронизируется с помощью RLock, Когда вы используете Manager Вы получаете SynManager объект, управляющий процессом сервера, который позволяет манипулировать значениями объекта другими процессами. Вы можете создать несколько прокси, используя один и тот же менеджер; нет необходимости создавать нового менеджера в вашем цикле:

manager = Manager()
for i in range(5):
    new_value = manager.Value('i', 0)

Manager могут быть разделены между компьютерами, в то время как Value ограничен одним компьютером. Value будет быстрее (запустите приведенный ниже код, чтобы увидеть), поэтому я думаю, что вы должны использовать это, если вам не нужно поддерживать произвольные объекты или обращаться к ним по сети.

import time
from multiprocessing import Process, Manager, Value

def foo(data, name=''):
    print type(data), data.value, name
    data.value += 1

if __name__ == "__main__":
    manager = Manager()
    x = manager.Value('i', 0)
    y = Value('i', 0)

    for i in range(5):
        Process(target=foo, args=(x, 'x')).start()
        Process(target=foo, args=(y, 'y')).start()

    print 'Before waiting: '
    print 'x = {0}'.format(x.value)
    print 'y = {0}'.format(y.value)

    time.sleep(5.0)
    print 'After waiting: '
    print 'x = {0}'.format(x.value)
    print 'y = {0}'.format(y.value)

Подвести итоги:

  1. использование Manager создавать несколько общих объектов, включая диктовки и списки. использование Manager обмениваться данными между компьютерами в сети.
  2. использование Value или же Array когда нет необходимости обмениваться информацией по сети и типы в ctypes достаточно для ваших нужд.
  3. Value быстрее чем Manager,

Предупреждение

Кстати, по возможности следует избегать совместного использования данных между процессами / потоками. Приведенный выше код, вероятно, будет работать как положено, но увеличит время, необходимое для выполнения foo и все станет странным. Сравните вышесказанное с:

def foo(data, name=''):
    print type(data), data.value, name
    for j in range(1000):
        data.value += 1

Вам понадобится Lock чтобы сделать эту работу правильно.

Я не особенно осведомлен обо всем этом, поэтому, возможно, кто-то еще придет и предложит больше понимания. Я подумал, что внесу ответ, так как этот вопрос не привлекает внимания. Надеюсь, это немного поможет.

Другие вопросы по тегам