Flush
Flush

Reputation: 73

How to gather results from multiprocesses?

I have a problem with my python code. What I want is that each process writes in one dictionary. What I get is that every process writes into his own dictionary.

To make it clear: After running the code: I get this output:

P 0: {0: 1}
P 2: {2: 1}
P 4: {4: 1}
P 6: {6: 1}
P 8: {8: 1}
All: {}

What I want is:

P 0: {0: 1}
P 2: {2: 1}
P 4: {4: 1}
P 6: {6: 1}
P 8: {8: 1}
All: {0: 1, 2: 1, 4: 1, 6: 1, 8: 1}

Here is my sample Code:

from multiprocessing import Process, Lock, cpu_count

class multiprocessingExample():

    global d
    d = {}
    global lock
    lock = Lock()

    def __init__(self):
        pass

    def proc(self, num):

            global lock
            global d
            with lock:
                if(num in d):
                    d[num] = d[num] + 1
                else:
                    d[num] = 1
                print("P " + str(num) + ": " + str(d))

    def main(self):
        jobs = []

        for i in range(0, 10):
            if(i%2 == 0):
                p = Process(target=self.proc, args=(i,))
                jobs.append(p)

        for job in jobs:
            job.start()

        for job in jobs:
            job.join()

        print("All: " + str(d))

obj = multiprocessingExample()
obj.main()

It'd be great if you could tell me what's going wrong.

Upvotes: 7

Views: 2405

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180391

Don't use global, use a Manager.dict:

from multiprocessing import Process, Lock, Manager


class multiprocessingExample():
    def __init__(self):
        self.m = Manager()
        self.d = self.m.dict()
        self.lock = Lock()

    def proc(self, num):
        with self.lock:
            if (num in self.d):
                self.d[num] = d[num] + 1
            else:
                self.d[num] = 1
            print("P " + str(num) + ": " + str(self.d))   
    def main(self):
        jobs = []
            for i in range(0, 10):
            if (i % 2 == 0):
                p = Process(target=self.proc, args=(i,))
                jobs.append(p)    

        for job in jobs:
            job.start()    
        for job in jobs:
            job.join()    
        print("All: " + str(self.d))


obj = multiprocessingExample()
obj.main()

Which will output something like:

P 0: {0: 1}
P 2: {0: 1, 2: 1}
P 4: {0: 1, 2: 1, 4: 1}
P 8: {0: 1, 8: 1, 2: 1, 4: 1}
P 6: {0: 1, 8: 1, 2: 1, 4: 1, 6: 1}
All: {0: 1, 8: 1, 2: 1, 4: 1, 6: 1}

Upvotes: 8

ForceBru
ForceBru

Reputation: 44828

You seem to be using global incorrectly. It's used to make sure that whenever you refer to variable you mean the one in global scope:

#global scope
count = 0

def fun():
    #local variables
    local_count = 0

    # 'when I say "do something to `count`",
    # I mean the global variable'

    global count

    count += 1

You need to declare these variables first, like this:

from multiprocessing import Process, Lock, cpu_count

# initialize global variables

d = {}
lock = Lock()

class multiprocessingExample():

    global d
    # here you're overwriting them, so previous
    # values are no longer available.
    # you probably shouldn't do this, better initialize them
    # in global namespace

    #d = {}
    global lock

Note that you can also do global d, lock, something_else, so you don't need to write global every time.

Upvotes: 2

Related Questions