如何在 Multiprocessing Pool.map 中正确引用 class 的实例?
How to properly reference to instances of a class in Multiprocessing Pool.map?
假设我定义了以下 class:
class Animal:
def __init__(self):
self.isAlive = True
连同以下功能:
def Kill_Animal(animal):
animal.isAlive = False
现在,如果我创建一个动物列表,如下所示:
AnimalsList = [Animal() for i in range(0,5)]
如果函数应用于列表中 Animal Class 的任何实例,isAlive 属性将更改为 False。但是,如果我想将此函数应用于此列表并通过多处理库更改其内容,正确的方法是什么?
我试过以下方法:
from multiprocessing import Process, Pool
pool = Pool()
pool.map(Kill_Animal, AnimalsList[0:3])
但是,如果我尝试检查列表中所有元素的属性,结果如下:
[print(animal.isAlive) for animal in AnimalsList]
输出:True True True True True
此外,如果我尝试检查在运行时通过 Pool.Map 传递给 Kill_Animal 函数的对象的 ID,它与对象自己的 ID 不匹配。我熟悉 Python 的对象调用引用,但这里发生了什么?
学习了multiprocessing documentation,理解了概念的误读
使用 multiprocessing,即使 class 的实例作为参数传递,ID 与调用方法中的 ID 不同也是有意义的,因为现在我们在不同的 Process 中工作,因此这个对象是原始对象的副本,并且不对应于内存中的相同位置。因此,副本中的任何更改都不会影响其原始实例。
为了使用并行和共享状态,必须应用一个不同的概念,多线程,如 thread-based parallellism documentation. The difference between multithreading and multiprocessing has been thoroughly discussed here: Multiprocessing vs Threading Python
中可用
回到最初的问题,有两种简单的方法可以实现遍历列表并应用函数:
1。使用 multiprocessing.dummy:
multiprocessing.dummy replicates the API of multiprocessing but is no more than a wrapper around the threading module.
所以答案可以写成:
import multiprocessing.dummy as mp
p = mp.Pool(3) # With 3 being the number of threads.
p.map(Kill_Animal, AnimalsList)
p.close()
p.join()
[print(animal.isAlive) for animal in AnimalsList]
输出:假假假假假假假
2。使用 Queue:
from queue import Queue
from threading import Thread
# Creates the hunter thread.
def hunter():
while True:
animal = q.get()
Kill_Animal(animal)
q.task_done()
num_hunter_threads = 3
q = Queue()
#Initialize the threads
for i in range(num_hunter_threads):
t = Thread(target=hunter)
t.daemon = True
t.start()
#Adds each animal in the list to the Queue.
for animal in AnimalsList:
q.put(animal)
#Execute the jobs in the queue.
q.join()
[print(animal.isAlive) for animal in AnimalsList)
输出:假假假假假假假
假设我定义了以下 class:
class Animal:
def __init__(self):
self.isAlive = True
连同以下功能:
def Kill_Animal(animal):
animal.isAlive = False
现在,如果我创建一个动物列表,如下所示:
AnimalsList = [Animal() for i in range(0,5)]
如果函数应用于列表中 Animal Class 的任何实例,isAlive 属性将更改为 False。但是,如果我想将此函数应用于此列表并通过多处理库更改其内容,正确的方法是什么?
我试过以下方法:
from multiprocessing import Process, Pool
pool = Pool()
pool.map(Kill_Animal, AnimalsList[0:3])
但是,如果我尝试检查列表中所有元素的属性,结果如下:
[print(animal.isAlive) for animal in AnimalsList]
输出:True True True True True
此外,如果我尝试检查在运行时通过 Pool.Map 传递给 Kill_Animal 函数的对象的 ID,它与对象自己的 ID 不匹配。我熟悉 Python 的对象调用引用,但这里发生了什么?
学习了multiprocessing documentation,理解了概念的误读
使用 multiprocessing,即使 class 的实例作为参数传递,ID 与调用方法中的 ID 不同也是有意义的,因为现在我们在不同的 Process 中工作,因此这个对象是原始对象的副本,并且不对应于内存中的相同位置。因此,副本中的任何更改都不会影响其原始实例。
为了使用并行和共享状态,必须应用一个不同的概念,多线程,如 thread-based parallellism documentation. The difference between multithreading and multiprocessing has been thoroughly discussed here: Multiprocessing vs Threading Python
中可用回到最初的问题,有两种简单的方法可以实现遍历列表并应用函数:
1。使用 multiprocessing.dummy:
multiprocessing.dummy replicates the API of multiprocessing but is no more than a wrapper around the threading module.
所以答案可以写成:
import multiprocessing.dummy as mp
p = mp.Pool(3) # With 3 being the number of threads.
p.map(Kill_Animal, AnimalsList)
p.close()
p.join()
[print(animal.isAlive) for animal in AnimalsList]
输出:假假假假假假假
2。使用 Queue:
from queue import Queue
from threading import Thread
# Creates the hunter thread.
def hunter():
while True:
animal = q.get()
Kill_Animal(animal)
q.task_done()
num_hunter_threads = 3
q = Queue()
#Initialize the threads
for i in range(num_hunter_threads):
t = Thread(target=hunter)
t.daemon = True
t.start()
#Adds each animal in the list to the Queue.
for animal in AnimalsList:
q.put(animal)
#Execute the jobs in the queue.
q.join()
[print(animal.isAlive) for animal in AnimalsList)
输出:假假假假假假假