Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared variable in python's multiprocessing

First question is what is the difference between Value and Manager().Value?

Second, is it possible to share integer variable without using Value? Below is my sample code. What I want is getting a dict with a value of integer, not Value. What I did is just change it all after the process. Is there any easier way?

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 
like image 842
user2435611 Avatar asked Jun 29 '13 06:06

user2435611


People also ask

Does Python multiprocessing use shared memory?

shared_memory — Shared memory for direct access across processes. New in version 3.8. This module provides a class, SharedMemory , for the allocation and management of shared memory to be accessed by one or more processes on a multicore or symmetric multiprocessor (SMP) machine.

What is shared memory Python?

Shared memory can be a very efficient way of handling data in a program that uses concurrency. Python's mmap uses shared memory to efficiently share large amounts of data between multiple Python processes, threads, and tasks that are happening concurrently.


1 Answers

When you use Value you get a ctypes object in shared memory that by default is synchronized using RLock. When you use Manager you get a SynManager object that controls a server process which allows object values to be manipulated by other processes. You can create multiple proxies using the same manager; there is no need to create a new manager in your loop:

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

The Manager can be shared across computers, while Value is limited to one computer. Value will be faster (run the below code to see), so I think you should use that unless you need to support arbitrary objects or access them over a network.

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) 

To summarize:

  1. Use Manager to create multiple shared objects, including dicts and lists. Use Manager to share data across computers on a network.
  2. Use Value or Array when it is not necessary to share information across a network and the types in ctypes are sufficient for your needs.
  3. Value is faster than Manager.

Warning

By the way, sharing data across processes/threads should be avoided if possible. The code above will probably run as expected, but increase the time it takes to execute foo and things will get weird. Compare the above with:

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

You'll need a Lock to make this work correctly.

I am not especially knowledgable about all of this, so maybe someone else will come along and offer more insight. I figured I would contribute an answer since the question was not getting attention. Hope that helps a little.

like image 92
ChrisP Avatar answered Sep 20 '22 18:09

ChrisP