简体   繁体   English

Python多处理共享全局值

[英]Python Multiprocessing sharing of global values

What i am trying to do is to make use of global variable by each process. 我想要做的是通过每个过程利用全局变量。 But my process is not taking the global values 但我的过程并没有采取全球价值观

import multiprocessing

count = 0 

def smile_detection(thread_name):
    global count

    for x in range(10):
        count +=1
        print thread_name,count

    return count    

x = multiprocessing.Process(target=smile_detection, args=("Thread1",))
y = multiprocessing.Process(target=smile_detection, args=("Thread2",))
x.start()
y.start()

I am getting output like 我得到的输出就像

Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 1
Thread2 2
.
.
Thread2 9
Thread2 10

what I want is 我想要的是什么

Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 11
Thread2 12
.
.
Thread2 19
Thread2 20

What I have to do to achieve this? 我需要做些什么才能实现这一目标?

Unlike threading, multiprocessing is a bit trickier to handle shared state due to forking (or spawning) of a new process. 与线程不同,由于新进程的分叉(或产生),多处理处理共享状态有点棘手。 Especially in windows. 特别是在窗户。 To have a shared object, use a multiprocessing.Array or multiprocessing.Value. 要拥有共享对象,请使用multiprocessing.Array或multiprocessing.Value。 In the case of the array, you can, in each process, dereference its memory address in another structure, eg an numpy array. 在数组的情况下,您可以在每个进程中取消引用其他结构中的内存地址,例如numpy数组。 In your case, I would do something like this: 在你的情况下,我会做这样的事情:

import multiprocessing, ctypes

count = multiprocessing.Value(ctypes.c_int, 0)  # (type, init value)

def smile_detection(thread_name, count):

    for x in range(10):
        count.value +=1
        print thread_name,count

    return count    

x = multiprocessing.Process(target=smile_detection, args=("Thread1", count))
y = multiprocessing.Process(target=smile_detection, args=("Thread2", count))
x.start()
y.start()

Try doing it like this: 尝试这样做:

import multiprocessing

def smile_detection(thread_name, counter, lock):
    for x in range(10):
        with lock:
            counter.value +=1
            print thread_name, counter.value  


count = multiprocessing.Value('i',  0)
lock = multiprocessing.Lock()
x = multiprocessing.Process(target=smile_detection, args=("Thread1", count, lock))
y = multiprocessing.Process(target=smile_detection, args=("Thread2", count, lock))
x.start()
y.start()
x.join()
y.join()

First problem is that global variables are not shared between processes. 第一个问题是全局变量不在进程之间共享。 You need to use a mechanism with some type of threadsafe locking or synchronization. 您需要使用具有某种线程安全锁定或同步类型的机制。 We can use multiprocessing.Value('i', 0) to create a threadsafe, synchronized integer value. 我们可以使用multiprocessing.Value('i', 0)来创建线程安全的同步整数值。 We use our multiprocessing.Lock() to ensure that only one thread can update the counter at a time. 我们使用multiprocessing.Lock()来确保一次只有一个线程可以更新计数器。

If you really want to use the global variable, you can use multiprocessing.Manager() , which can stay in a global variable: 如果您真的想使用全局变量,可以使用multiprocessing.Manager() ,它可以保留在全局变量中:

import multiprocessing

count = multiprocessing.Manager().Value('i',  0)
lock = multiprocessing.Manager().Lock()

def smile_detection(thread_name):
    global count, lock

    for x in range(10):
        with lock:
            counter.value +=1
            print thread_name, counter.value  

x = multiprocessing.Process(target=smile_detection, args=("Thread1",))
y = multiprocessing.Process(target=smile_detection, args=("Thread2",))
x.start()
y.start()
x.join()
y.join()

But, personally, I like the first method better, as a Manager() overcomplicates this. 但是,就个人而言,我更喜欢第一种方法,因为Manager()过于复杂。

Here's the output now: 这是现在的输出:

$ python test.py
Thread1 1
Thread1 2
Thread1 3
Thread1 4
Thread1 5
Thread1 6
Thread1 7
Thread1 8
Thread1 9
...
Thread2 15
Thread2 16
Thread2 17
Thread2 18
Thread2 19
Thread2 20

You can use a multiprocessing.Value : 您可以使用multiprocessing.Value

Return a ctypes object allocated from shared memory. 返回从共享内存分配的ctypes对象。 By default the return value is actually a synchronized wrapper for the object. 默认情况下,返回值实际上是对象的同步包装器。

The code would be like this: 代码如下:

import multiprocessing

count = multiprocessing.Value('i', 0)

def smile_detection(thread_name, count):
    for x in range(10):
        count += 1
        print thread_name, count

x = multiprocessing.Process(target=smile_detection, args=("Thread1",count))
y = multiprocessing.Process(target=smile_detection, args=("Thread2",count))

x.start()
y.start()
x.join()
y.join()

Be aware that the output will likely not be the one that you expect. 请注意,输出可能不是您期望的输出。 In your expected output in fact, all the iterations of Thread 1 come before the ones of Thread 2 . 事实上,在您的预期输出中, Thread 1所有迭代都在Thread 2的迭代之前。 That's not the case in multi-threaded applications. 在多线程应用程序中并非如此。 If you want that to happen, well, you do not want it to be threaded! 如果你希望这种情况发生,那么,你不希望它被线程化!

To share data between processes you to need to let mutiprocessing.Manager manage the shared data: 要在进程之间共享数据,您需要让mutiprocessing.Manager管理共享数据:

count = multiprocessing.Manager().Value('i', 0) # creating shared variable
lock = multiprocessing.Manager().Lock() # we'll use lock to acquire lock on `count` before count += 1

def smile_detection(thread_name):
    global count

    for x in range(10):
        lock.acquire()
        count +=1
        lock.release()
        print thread_name,count

    return count   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM