Python 全局值的多处理共享
Python Multiprocessing sharing of 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()
我得到的输出类似于
Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 1
Thread2 2
.
.
Thread2 9
Thread2 10
我要的是
Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 11
Thread2 12
.
.
Thread2 19
Thread2 20
我需要做什么才能实现这一目标?
与线程不同,由于新进程的分叉(或产生),多处理处理共享状态有点棘手。特别是在 windows。要拥有共享对象,请使用 multiprocessing.Array 或 multiprocessing.Value。对于数组,您可以在每个进程中取消引用另一个结构中的内存地址,例如 numpy 数组。在你的情况下,我会做这样的事情:
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()
要在进程之间共享数据,您需要让 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
尝试这样做:
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()
第一个问题是进程之间不共享全局变量。您需要使用具有某种类型的线程安全锁定或同步的机制。我们可以使用multiprocessing.Value('i', 0)
to create a threadsafe, synchronized integer value. We use our multiprocessing.Lock()
来确保一次只有一个线程可以更新计数器。
如果真的要使用全局变量,可以使用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()
但是,就我个人而言,我更喜欢第一种方法,因为 Manager()
过于复杂了。
这是现在的输出:
$ 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
您可以使用 multiprocessing.Value
:
Return a ctypes object allocated from shared memory. By default the return value is actually a synchronized wrapper for the object.
代码应该是这样的:
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()
请注意,输出可能不是您所期望的。事实上,在您的预期输出中,Thread 1
的所有迭代都在 Thread 2
的迭代之前。在多线程应用程序中情况并非如此。如果你希望发生这种情况,那么,你不希望它被线程化!
我想做的是让每个进程都使用全局变量。 但是我的过程没有采用全局值
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()
我得到的输出类似于
Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 1
Thread2 2
.
.
Thread2 9
Thread2 10
我要的是
Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 11
Thread2 12
.
.
Thread2 19
Thread2 20
我需要做什么才能实现这一目标?
与线程不同,由于新进程的分叉(或产生),多处理处理共享状态有点棘手。特别是在 windows。要拥有共享对象,请使用 multiprocessing.Array 或 multiprocessing.Value。对于数组,您可以在每个进程中取消引用另一个结构中的内存地址,例如 numpy 数组。在你的情况下,我会做这样的事情:
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()
要在进程之间共享数据,您需要让 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
尝试这样做:
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()
第一个问题是进程之间不共享全局变量。您需要使用具有某种类型的线程安全锁定或同步的机制。我们可以使用multiprocessing.Value('i', 0)
to create a threadsafe, synchronized integer value. We use our multiprocessing.Lock()
来确保一次只有一个线程可以更新计数器。
如果真的要使用全局变量,可以使用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()
但是,就我个人而言,我更喜欢第一种方法,因为 Manager()
过于复杂了。
这是现在的输出:
$ 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
您可以使用 multiprocessing.Value
:
Return a ctypes object allocated from shared memory. By default the return value is actually a synchronized wrapper for the object.
代码应该是这样的:
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()
请注意,输出可能不是您所期望的。事实上,在您的预期输出中,Thread 1
的所有迭代都在 Thread 2
的迭代之前。在多线程应用程序中情况并非如此。如果你希望发生这种情况,那么,你不希望它被线程化!