我正在学习如何在Python中使用threading
和multiprocessing
模块来并行运行某些操作并加速我的代码。
我发现很难理解一个threading.Thread()
对象与一个对象之间的区别是什么(也许是因为我没有任何理论背景)multiprocessing.Process()
。
另外,对我来说,如何实例化一个作业队列并使其只有4个(例如)并行运行,而另一个则等待资源释放后再执行,对我来说也不是很清楚。
我发现文档中的示例很清楚,但并不十分详尽。一旦我尝试使事情复杂化,我就会收到很多奇怪的错误(例如无法腌制的方法,等等)。
那么,什么时候应该使用threading
andmultiprocessing
模块?
您能否将我链接到一些资源,以解释这两个模块的概念以及如何在复杂的任务中正确使用它们?
什么朱利奥·佛朗哥说,对于多线程多处理与真 一般 。
但是,Python
*还有一个问题:有一个全局解释器锁,可以防止同一进程中的两个线程同时运行Python代码。这意味着,如果您有8个内核,并且将代码更改为使用8个线程,它将无法使用800%的CPU并无法以8倍的速度运行;它会使用相同的100%CPU,并以相同的速度运行。(实际上,它的运行速度会稍慢一些,因为即使您没有任何共享数据,线程处理也会带来额外的开销,但现在暂时忽略它。)
也有例外。如果代码的繁重计算实际上不是在Python中发生,而是在某些具有自定义C代码且可以正确执行GIL处理的库中(例如numpy应用程序),那么线程将为您带来预期的性能收益。如果繁重的计算是由您运行并等待的某个子进程完成的,则情况也是如此。
更重要的是,在某些情况下,这无关紧要。例如,网络服务器花费大部分时间来读取网络上的数据包,而GUI应用花费大部分时间来等待用户事件。在网络服务器或GUI应用程序中使用线程的原因之一是允许您执行长时间运行的“后台任务”,而又不会阻止主线程继续为网络数据包或GUI事件提供服务。这在Python线程上工作得很好。(从技术上讲,这意味着Python线程为您提供了并发性,即使它们没有为您提供核心并行性。)
但是,如果您使用纯Python编写受CPU约束的程序,则使用更多线程通常无济于事。
对于GIL,使用单独的进程没有这种问题,因为每个进程都有自己的单独的GIL。当然,与其他语言相比,线程和进程之间仍然具有所有相同的权衡关系–在进程之间共享数据比在线程之间共享更加困难,而且成本更高,运行大量进程或创建和销毁这些开销可能会很高它们经常出现,等等。但是GIL在处理方面的平衡上占了很大比重,对于C或Java而言,这是不正确的。因此,与使用C或Java相比,您会发现在Python中使用多处理的频率更高。
同时,Python的“包含电池”理念带来了一些好消息:编写代码很容易,只需进行一次更改即可在线程和进程之间来回切换。
如果您根据独立的“作业”来设计代码,除了输入和输出,这些作业不与其他作业(或主程序)共享任何内容,则可以使用该concurrent.futures
库在线程池周围编写代码,如下所示:
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
executor.submit(job, argument)
executor.map(some_function, collection_of_independent_things)
# ...
您甚至可以获取这些作业的结果,并将其传递给其他作业,按执行顺序或完成顺序等待操作;等等。阅读有关Future
对象的部分以获取详细信息。
现在,如果事实证明您的程序一直在使用100%CPU,并且添加更多线程只会使其速度变慢,那么您就遇到了GIL问题,因此您需要切换到进程。您要做的就是更改第一行:
with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
唯一真正的警告是,作业的自变量和返回值必须可腌制(而不需要花费太多时间或内存来腌制)才能使用跨流程。通常这不是问题,但有时是问题。
但是,如果您的工作不能自给自足怎么办?如果您可以根据 将消息 从一个 传递
到另一个的工作来设计代码,那仍然很容易。您可能必须使用threading.Thread
或multiprocessing.Process
代替依赖池。并且您将必须显式创建queue.Queue
或multiprocessing.Queue
对象。(还有很多其他选择,例如管道,套接字,带有斑点的文件等等。但是,要点是,如果执行器的自动魔力不足,则必须手动执行
某些 操作。)
但是,如果您甚至不能依靠消息传递怎么办?如果您需要两个作业来同时改变同一个结构并看到彼此的更改,该怎么办?在这种情况下,您将需要进行手动同步(锁定,信号量,条件等),并且,如果要使用进程,则需要显式的共享内存对象进行引导。这是多线程(或多处理)变得困难的时候。如果可以避免,那就太好了;如果不能,那么您将需要阅读的内容超过某人可以提供的答案。
通过评论,您想了解Python中的线程和进程之间的区别。的确,如果您阅读了朱利奥·佛朗哥(Giulio
Franco)的答案和我的知识以及我们所有的链接,那应该涵盖了所有内容……但是总结肯定会很有用,所以这里是:
ctypes
Types。threading
模块不具有该模块的某些功能multiprocessing
。(您可以使用multiprocessing.dummy
大多数缺少的API放在线程顶部,也可以使用更高级别的模块,例如concurrent.futures
,不必担心。)*出现此问题的实际上不是Python,而是该语言的“标准”实现CPython。其他一些实现没有JIL,例如Jython。
**如果您正在使用fork
start方法进行多处理(在大多数非Windows平台上可以使用),则每个子进程都将获得启动子级时父级拥有的任何资源,这可能是将数据传递给子级的另一种方式。
本文向大家介绍多处理和多线程之间的区别,包括了多处理和多线程之间的区别的使用技巧和注意事项,需要的朋友参考一下 多处理 多处理是指在单个系统中使用多个CPU /处理器。多个CPU可以并行运行,并一起执行多个进程。它们在很大程度上提高了计算能力。对称多重处理和非对称多重处理是两种类型的多重处理。 多线程 多线程是指由单个CPU执行的多个线程,使得每个线程以并行方式执行,并且CPU /处理器使用上下文
问题内容: 请告诉我之间的差异,并在模块。当我尝试代码时,这是我看到的主要区别: 我看到以下输出: 使用“ ThreadPool”: 我看到以下输出: 我的问题是: 为何每次在__main __()外运行? 没有产生新的进程?它只是创建新线程? 如果是这样,使用与仅使用模块之间有什么区别? 我在任何地方都没有看到任何官方文档,有人可以在哪里找到我吗? 问题答案: 该行为一样,唯一的区别在于使用线程
问题内容: 进程和线程之间的技术区别是什么? 我感到像“过程”这样的词已被过度使用,并且还有硬件和软件线程。像Erlang这样的语言的轻量级进程怎么样?有确定的理由使用一个术语而不是另一个术语吗? 问题答案: 进程和线程都是独立的执行序列。典型的区别是(同一进程的)线程在共享内存空间中运行,而进程在单独的内存空间中运行。 我不确定您可能指的是“硬件”还是“软件”线程。线程是一种操作环境功能,而不是
我的工作应该使用并行技术,我是python的新用户。因此,我想知道您是否可以分享一些关于python和模块的资料。这两者有什么区别?
问题内容: Python模块和Python包之间有什么区别? 问题答案: 模块是单个文件(一个或多个文件),可在一个导入下导入并使用。例如 包是目录中提供包层次结构的模块的集合。
问题内容: 我已经看到许多项目使用 模块而不是 标准库中的模块。另外,有许多不同的模块。为什么要使用这些替代方法而不是标准库中的替代方法? 问题答案: 是 ,已添加到stdlib中。但是自从2.6中添加以来,它具有处理更多Python版本(2.4+)的优势。 的更新频率也比Python高,因此,如果您需要(或想要)最新版本,则尽可能使用它自己。 我认为,一种好的做法是将其中一个作为后备。