Python 什么';线程池与多处理模块中的池之间的区别是什么?
Python 什么';线程池与多处理模块中的池之间的区别是什么?,python,python-3.x,multiprocessing,threadpool,python-multiprocessing,Python,Python 3.x,Multiprocessing,Threadpool,Python Multiprocessing,多处理模块中的ThreadPool和Pool有什么区别。当我尝试我的代码时,我看到的主要区别是: from multiprocessing import Pool import os, time print("hi outside of main()") def hello(x): print("inside hello()") print("Proccess id: ", os.getpid()) time.sleep(3) return x*x if _
多处理
模块中的ThreadPool
和Pool
有什么区别。当我尝试我的代码时,我看到的主要区别是:
from multiprocessing import Pool
import os, time
print("hi outside of main()")
def hello(x):
print("inside hello()")
print("Proccess id: ", os.getpid())
time.sleep(3)
return x*x
if __name__ == "__main__":
p = Pool(5)
pool_output = p.map(hello, range(3))
print(pool_output)
我看到以下输出:
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
inside hello()
Proccess id: 13268
inside hello()
Proccess id: 11104
inside hello()
Proccess id: 13064
[0, 1, 4]
hi outside of main()
inside hello()
inside hello()
Proccess id: 15204
Proccess id: 15204
inside hello()
Proccess id: 15204
[0, 1, 4]
使用“线程池”:
我看到以下输出:
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
inside hello()
Proccess id: 13268
inside hello()
Proccess id: 11104
inside hello()
Proccess id: 13064
[0, 1, 4]
hi outside of main()
inside hello()
inside hello()
Proccess id: 15204
Proccess id: 15204
inside hello()
Proccess id: 15204
[0, 1, 4]
我的问题是:
- 为什么每次都在
池中运行“outside\uuuu main\uuuuuuuuuo()”
不会产生新进程吗?它只是创建新线程multiprocessing.pool.ThreadPool
- 如果是这样,那么使用
与仅使用多处理.pool.ThreadPool
模块有什么区别线程处理
我在任何地方都没有看到任何关于
ThreadPool
的官方文档,有人能帮我找到它吗?多处理.pool.ThreadPool的行为与多处理.pool
相同,唯一的区别是使用线程而不是进程来运行worker逻辑
你看到的原因
hi outside of main()
使用多处理.Pool
多次打印是因为该池将包含5个独立的进程。每个进程将初始化自己的Python解释器并加载模块,从而再次执行顶级的print
请注意,只有在使用spawn
进程创建方法(仅Windows上可用的方法)时才会发生这种情况。如果使用fork
one(Unix),您将看到与线程一样只打印一次消息
multiprocessing.pool.ThreadPool
没有文档记录,因为它的实现从未完成。它缺乏测试和文档。您可以在中看到它的实现
我相信下一个自然的问题是:何时使用基于线程的池,何时使用基于进程的池
经验法则是:
- IO绑定作业->
多处理.pool.ThreadPool
- CPU绑定作业->
多处理.Pool
- 混合作业->取决于工作负载,由于进程隔离带来的优势,我通常更喜欢
多处理.Pool
在Python 3上,您可能想看看池实现。我知道,由于Python中的GIL,Python的多线程看起来像多线程,但它不是真实的。如果希望利用python的多核功能,则需要使用多处理。在现代计算机中,创建一个进程和创建一个线程的成本几乎相同。创建一个线程的成本可能与创建一个进程的成本相似,但是线程之间的通信与进程之间的通信的成本非常不同(除非您使用共享内存)。此外,您对GIL的评论只有一部分是正确的:它是在I/O操作期间发布的,并且由一些库(例如numpy)发布,甚至是在CPU限制的操作期间。尽管如此,GIL仍然是在Python中使用单独进程的最终原因。@Yves这在*nix上可能是正确的,通过使用
fork
,但在Windows上不是正确的,并且没有考虑到进程与线程(在所有平台上)之间通信的额外开销、限制和复杂性。要回答有关线程化
与线程池
的问题,在线程化
中,没有简单直接的方法获取辅助函数的返回值。然而,在ThreadPool
中,您可以轻松获得辅助函数的返回值。谢谢您的回答。我只想理解这句话:请注意,只有在使用spawn进程创建方法时才会发生这种情况(只有在Windows上可用的方法)。如果您使用fork one(Unix),您将看到与线程一样只打印一次消息。我假设,当我调用“map()”或“Pool()”时,“spawn”和“fork”是隐式的?或者这是我可以控制的吗?我在上面提到start方法时给你的链接中有解释。您可以控制它,但启动方法的可用性取决于操作系统平台。我假设您使用的是Windows,因为默认的启动策略是spawn
one。如果是这样,那就没什么可做的了,因为Windows只支持spawn
。关于ThreadPool
未完成的实现的评论在2019年Python 3.7版中仍然有效吗?是的。正如您从链接的源代码和缺乏文档中所看到的那样。@MrR,这是绝对合理和正确的,但这并没有真正说明为什么IO绑定作业更喜欢线程池而不是池(进程);尽管如此,我认为这是可以简单地用常识来解释的,它涉及到完成整个子流程所需的时间,以及由于不能共享相同的资源而导致的额外开销。