I'm trying to write a multiprocessing program which shares one or more variables (values or matrix) between the child processes. In my current test program I'm trying to spawn two processes, each sharing the num variable. Each adds 1 to the variable and then prints. However, whenever I try to run the program it tells me a TypeError has occurred, saying 'Synchronized' object is not iterable. How can I get this to work?
The code is shown below:
import multiprocessing
import os
import time
def info(title):
print(title)
print('module name:', __name__)
print('parent process:', os.getppid())
print('process id:', os.getpid())
def f(num):
while True:
time.sleep(1.5)
num = num + 1
print("process 1: %i \n" % num)
if num > 50:
break
def f2(num):
while True:
num= num + 1
print("process 2: %i \n" % num)
time.sleep(1.9)
if num > 50:
break
if __name__ == '__main__':
data = multiprocessing.Value('i',0)
p = multiprocessing.Process(target=f, args=(data))
j = multiprocessing.Process(target=f2, args=(data))
p.start()
j.start()
"Synchronized' object is not iterable results from running the program when it tries to create the first process: p = multiprocessing.Process(target=f, args=(data))
I'm not sure whether using a queue would work as I'd eventually like to have a program which has a looping process and another which occasionally grabs the most recent result returned from the looping process.
You have several issues with your code:
multiprocessing.Value instance (num in your case), you must use the value attribute of that instance to read or write actual value of that shared variable.num.value = num.value + 1 with num.value += 1 as I have done, is not an atomic operation. It is equivalent to temp = num.value; temp += 1; num.value = temp, which means that this incrementing must take place under control of the lock provided for such synchronized instances to ensure that the value is truly incremeneted. Otherwise, two processes may read the same value and increment it to the same final value and you will have only incremented the value once instead of twice.multiprocessing.Process initializer should be an iterable where each element of the iterable becomes an argument to your worker functions f and f2. When you specify args=(data), the parentheses has no effect and is equivalent to simply specifying args=data and data is not an iterable. You needed to have args=(data,). Note the comma (',') such that (data,) is now a tuple (i.e. an iterable) containing the single element data instead of a parenthesized expression.import multiprocessing
import os
import time
def info(title):
print(title)
print('module name:', __name__)
print('parent process:', os.getppid())
print('process id:', os.getpid())
def f(num):
while True:
time.sleep(1.5)
with num.get_lock():
num.value += 1
print("process 1: %i \n" % num.value)
if num.value > 50:
break
def f2(num):
while True:
with num.get_lock():
num.value += 1
print("process 2: %i \n" % num.value)
time.sleep(1.9)
if num.value > 50:
break
if __name__ == '__main__':
data = multiprocessing.Value('i',0)
p = multiprocessing.Process(target=f, args=(data,))
j = multiprocessing.Process(target=f2, args=(data,))
p.start()
j.start()
p.join()
j.join()
print(data.value)
Prints:
...
process 2: 47
process 1: 48
process 2: 49
process 1: 50
process 2: 51
process 1: 52
52
But note that in the above code, each process acquires and hold the lock for a very long time shutting out any other process from acquiring the lock. We can minimize how long the lock is held in the following way (and so the program will complete sooner):
import multiprocessing
import os
import time
def info(title):
print(title)
print('module name:', __name__)
print('parent process:', os.getppid())
print('process id:', os.getpid())
def f(num):
while True:
time.sleep(1.5)
with num.get_lock():
num.value += 1
saved_value = num.value
print("process 1: %i \n" % saved_value)
if saved_value > 50:
break
def f2(num):
while True:
with num.get_lock():
num.value += 1
saved_value = num.value
print("process 2: %i \n" % saved_value)
time.sleep(1.9)
if saved_value > 50:
break
if __name__ == '__main__':
data = multiprocessing.Value('i',0)
p = multiprocessing.Process(target=f, args=(data,))
j = multiprocessing.Process(target=f2, args=(data,))
p.start()
j.start()
p.join()
j.join()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With