Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
256 views
in Technique[技术] by (71.8m points)

Python multiprocessing and shared memory - why do I get different results?

I'm testing some python code to share a numpy array between 2 processes.

from multiprocessing import Process, Semaphore, shared_memory
import numpy as np
import time

def reader(id, a, shm):
    exst_shm = shared_memory.SharedMemory(name=shm)
    b = np.ndarray(a.shape, dtype=a.dtype, buffer=exst_shm.buf)
        
    time.sleep(2)    
    print('FUNCTION VERSION: ', b[0])   
    

def worker(id, a, shm):
    exst_shm = shared_memory.SharedMemory(name=shm)
    b = np.ndarray(a.shape, dtype=a.dtype, buffer=exst_shm.buf) 
    b[0] += 10 


if __name__ == "__main__":
    a = np.array([0])
    shm = shared_memory.SharedMemory(create=True, size=a.nbytes) 
    c = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
    
    th1 = Process(target=reader, args=(1, a, shm.name))
    th2 = Process(target=worker, args=(2, a, shm.name))
    
    th1.start()
    th2.start()
    th1.join()
    th2.join()

The code above works fine and it prints out: FUNCTION VERSION: 10

from multiprocessing import Process, Semaphore, shared_memory
import numpy as np
import time

class Reader(Process):
    def __init__(self, id, a, shm):
        Process.__init__(self)
        
        exst_shm = shared_memory.SharedMemory(name=shm)
        b = np.ndarray(a.shape, dtype=a.dtype, buffer=exst_shm.buf) 
        
        time.sleep(2)    
        print('SUBCLASS VERSION: ', b[0])   
       
class Worker(Process):
    def __init__(self, id, a, shm):
        Process.__init__(self)
            
        exst_shm = shared_memory.SharedMemory(name=shm) 
        b = np.ndarray(a.shape, dtype=a.dtype, buffer=exst_shm.buf) 
        b[0] += 10
        
if __name__ == "__main__":
    a = np.array([0])
    shm = shared_memory.SharedMemory(create=True, size=a.nbytes) 
    c = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
    
    th1 = Reader(1, a, shm.name)
    th2 = Worker(2, a, shm.name)

    th1.start()
    th2.start()
    th1.join()
    th2.join()

However, when it's written as classes, it prints out: SUBCLASS VERSION: 0. Where does the difference come from and what is wrong with the code?

question from:https://stackoverflow.com/questions/65942502/python-multiprocessing-and-shared-memory-why-do-i-get-different-results

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You create classes in wrong way.

Normally start() runs method run() to execute target in new process.

When you create own class then you have to overwrite method run() and put your code inside run() and then it will run this code when you use start().

In your version it runs all your code in main process, not in new processes. First you create Reader() which sleeps 2s and prints result b[0], and later you create Worker() which adds b[0] += 10. And after that you start() processes - but they have nothing to do because you didn't overwrite run() and you don't have target in classes.

from multiprocessing import Process, Semaphore, shared_memory
import numpy as np
import time

class Reader(Process):
    def __init__(self, id, a, shm):
        Process.__init__(self)
        
        self.exst_shm = shared_memory.SharedMemory(name=shm)
        self.b = np.ndarray(a.shape, dtype=a.dtype, buffer=self.exst_shm.buf) 
        
    def run(self):            
        time.sleep(2)
        print('SUBCLASS VERSION: ', self.b[0])   
       
class Worker(Process):
    def __init__(self, id, a, shm):
        Process.__init__(self)
        
        self.exst_shm = shared_memory.SharedMemory(name=shm) 
        self.b = np.ndarray(a.shape, dtype=a.dtype, buffer=self.exst_shm.buf) 

    def run(self):            
        self.b[0] += 10
        
if __name__ == "__main__":
    a = np.array([0])
    shm = shared_memory.SharedMemory(create=True, size=a.nbytes) 
    c = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
    
    th1 = Reader(1, a, shm.name)
    th2 = Worker(2, a, shm.name)

    th1.start()
    th2.start()
    th1.join()
    th2.join()

BTW:

Using

import multiprocessing
print(multiprocessing.__file__)

you can find source code and see in process.py how it works.

def run(self):
    '''
    Method to be run in sub-process; can be overridden in sub-class
    '''
    if self._target:
        self._target(*self._args, **self._kwargs)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...