多处理模块中 Pool 对象和 Manager 对象之间的位置
the position between Pool object and Manager object in multiprocessing module
1 from multiprocessing import Pool, Manager
2
3
4 def test(num):
5 queue.put(num)
6
7
8 queue = Manager().Queue()
9 pool = Pool(5)
10
11 for i in range(30):
12 pool.apply_async(test, (i, ))
13
14 pool.close()
15 pool.join()
16
17 print(queue.qsize())
上面代码的输出是30。但是,如果第8行和第9行交换(见下面的代码),输出将是0。有没有人知道为什么?谢谢!
1 from multiprocessing import Pool, Manager
2
3
4 def test(num):
5 queue.put(num)
6
7
8 pool = Pool(5)
9 queue = Manager().Queue()
10
11 for i in range(30):
12 pool.apply_async(test, (i, ))
13
14 pool.close()
15 pool.join()
16
17 print(queue.qsize())
from multiprocessing import Process, Queue
def test():
queue.put(1)
p = Process(target=test)
queue = Queue()
p.start()
p.join()
print(queue.qsize())
输出为1,表示子进程将号码放入父进程创建的队列中。对吗?
我假设您使用的是基于 Unix 的操作系统,就像在 NT 操作系统上一样,您的逻辑很可能会崩溃。
要了解发生了什么,我们需要深入研究 multiprocessing
内部结构。在 Unix 上,当创建一个新进程时,使用 fork
原语。当进程分叉时,parent 继续执行并且 child 作为 parent.
的精确副本启动
Python 倾向于在 multiprocessing
模块中隐藏很多东西(我特别不喜欢那样)并导致很多误解。在您的逻辑中,fork
在您创建 Pool
时发生(第一个示例中的第 9 行,第二个示例中的第 8 行)。
在第一个示例中,children 继承了 parent 创建的 queue
object。因此,当他们共享同一个频道时,他们成功地进行了沟通。
在第二个中,parent 和 children 创建了他们自己的完全独立的 queue
objects。当 child 将一个元素放入 queue
时,它会将其放入自己的元素中,不被任何人共享。
在第三个也是最后一个示例中,您创建了一个 Process
object,然后是一个 Queue
,然后您在该过程中调用了 start
。猜猜 fork
什么时候发生?当您调用 start
而不是当您创建 Process
object 时。这就是 queue
成功共享的原因。当我说 multiprocessing
API 有点误导时,这就是我的意思。
1 from multiprocessing import Pool, Manager
2
3
4 def test(num):
5 queue.put(num)
6
7
8 queue = Manager().Queue()
9 pool = Pool(5)
10
11 for i in range(30):
12 pool.apply_async(test, (i, ))
13
14 pool.close()
15 pool.join()
16
17 print(queue.qsize())
上面代码的输出是30。但是,如果第8行和第9行交换(见下面的代码),输出将是0。有没有人知道为什么?谢谢!
1 from multiprocessing import Pool, Manager
2
3
4 def test(num):
5 queue.put(num)
6
7
8 pool = Pool(5)
9 queue = Manager().Queue()
10
11 for i in range(30):
12 pool.apply_async(test, (i, ))
13
14 pool.close()
15 pool.join()
16
17 print(queue.qsize())
from multiprocessing import Process, Queue
def test():
queue.put(1)
p = Process(target=test)
queue = Queue()
p.start()
p.join()
print(queue.qsize())
输出为1,表示子进程将号码放入父进程创建的队列中。对吗?
我假设您使用的是基于 Unix 的操作系统,就像在 NT 操作系统上一样,您的逻辑很可能会崩溃。
要了解发生了什么,我们需要深入研究 multiprocessing
内部结构。在 Unix 上,当创建一个新进程时,使用 fork
原语。当进程分叉时,parent 继续执行并且 child 作为 parent.
Python 倾向于在 multiprocessing
模块中隐藏很多东西(我特别不喜欢那样)并导致很多误解。在您的逻辑中,fork
在您创建 Pool
时发生(第一个示例中的第 9 行,第二个示例中的第 8 行)。
在第一个示例中,children 继承了 parent 创建的 queue
object。因此,当他们共享同一个频道时,他们成功地进行了沟通。
在第二个中,parent 和 children 创建了他们自己的完全独立的 queue
objects。当 child 将一个元素放入 queue
时,它会将其放入自己的元素中,不被任何人共享。
在第三个也是最后一个示例中,您创建了一个 Process
object,然后是一个 Queue
,然后您在该过程中调用了 start
。猜猜 fork
什么时候发生?当您调用 start
而不是当您创建 Process
object 时。这就是 queue
成功共享的原因。当我说 multiprocessing
API 有点误导时,这就是我的意思。