Общая переменная в многопроцессорности python

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

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

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)

Подводя итог:

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

Внимание

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

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

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

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