本文的目的是解释为何在Python中须要多线程和多处理,什么时候使用多线程和多进程,以及它们能怎样提升咱们程序的性能。数据库
假设咱们的量化模型须要从多个网站爬取一些数据,咱们将要对比用单线程和多线程的方法有何性能上的差异。数组
1,单线程,单进程网络
在单线程、单进程中,咱们将用for循环读取一个url列表。多线程
如您所见,咱们只是使用for循环一个接一个地遍历url并读取响应。咱们可使用IPython的%%time函数对消耗的时间进行统计,这个读取13个网页的任务大约须要12秒钟。函数
Python学习交流群:1004391443性能
2,多线程学习
如今咱们改进一下这个程序,咱们能够将读取url的任务分配给多个线程来完成,而不是只让一个线程去逐一读取。网站
好比4个线程:url
8个线程:操作系统
16个线程:
用到16个线程时,这个任务的耗时已经从12.3秒缩短到了1.32秒。
使用多线程能够显著加快许多与io绑定的任务。在这里,读取url所花费的大部分时间是因为网络延迟。与io绑定的程序大部分时间都在等待输入/输出,无所事事。这多是来自网络、数据库、文件甚至用户的I/O。这种I/O每每要花费大量的时间,由于源自己可能须要在传递I/O以前执行本身的处理。例如,CPU的工做速度比网络链接传输数据的速度快得多。
多线程能够显著提升咱们爬取网页任务的效率。
3,多重处理
另外一个能够提升效率的手段是多重处理。
好比咱们有一个任务是计算100万之内全部质数的和。
若是只用单个进程:
若是使用多进程:
和多线程相似,多进程也是将任务(好比判断一系列数是不是质数)拆分再汇总,以此提升效率。
因为现代CPU一般有多个核心,咱们能够经过使用多处理模块来加快CPU绑定任务的速度。CPU绑定任务是花费大部分时间在CPU上执行计算的程序(数学计算、图像处理等)。若是计算能够彼此独立地执行,咱们就能够将它们分配到可用的CPU内核中,从而显著提升处理速度。
咱们所要作的就是:
1,定义要应用的函数
2,准备要应用功能的项目列表
3,使用Pool生成进程。传递给Pool()的数字将是生成的进程数。在with语句中嵌入能够确保在完成执行后终止进程。
4,使用池进程的map函数组合输出。映射函数的输入是要应用于每一个项的函数,以及项列表。
注意:能够定义该函数,以便执行任何能够并行执行的任务。例如,函数可能包含将计算结果写入文件的代码。
那么,为何咱们须要单独的多处理和多线程呢?若是您尝试使用多线程来提升CPU绑定任务的性能,而当进程数超过某个数值时,您可能会注意到,实际上获得的是性能降低。让咱们看看为何会这样。
由于Python也带有全局解释器锁(GIL)。Python会很乐意让用户生成任意数量的线程,可是GIL确保在任何给定的时间只有一个线程执行。
对于一个io绑定的任务,这彻底没问题。一个线程向一个URL发出请求,当它等待响应时,能够将该线程替换为向另外一个URL发出另外一个请求的另外一个线程。由于一个线程在收到响应以前不须要作任何事情,因此在给定的时间内只执行一个线程并不重要。
对于CPU绑定的任务,由于一次只执行一个线程,即便生成多个线程,而且每一个线程都有本身的数目来检查素数,CPU仍然一次只处理一个线程。实际上,这些数字仍然会被一个接一个地检查。若是在CPU绑定的任务中使用多线程,那么处理多线程的开销将致使性能降低。
为了克服这个“限制”,咱们使用了多处理模块。多处理不是使用线程,而是使用多个进程。每一个进程都有本身的解释器和内存空间,所以GIL不会阻止任何事情。本质上,每一个进程使用不一样的CPU内核同时处理不一样的数字。
您可能会注意到,与使用简单的for循环,甚至多线程相比,使用多处理时CPU利用率要高得多。这是由于您的程序使用多个CPU内核,而不只仅是一个内核。
请记住,多处理自己就有管理多个进程的开销,这一般比多线程开销更大。(多处理生成一个单独的解释器,并为每一个进程分配一个单独的内存空间)这意味着,根据经验,当可使用轻量级多线程时,最好使用它(io绑定任务)。当CPU处理成为瓶颈时,一般须要调用多处理模块。但请记住,能力越大,责任越大。
若是一次生成的进程超过CPU的处理能力,您将注意到性能开始降低。这是由于操做系统如今必须作更多的工做来交换CPU内核内外的进程,由于您的进程比内核多。实际状况可能比简单的解释要复杂得多,但这是基本思想。当咱们达到16个进程时,您能够看到个人系统性能降低。这是由于个人CPU只有16个逻辑核心。
4,总结
对于io绑定的任务,使用多线程能够提升性能。
对于io绑定的任务,使用多处理也能够提升性能,可是开销每每比使用多线程高。
Python GIL意味着在Python程序的任何给定时间内只能执行线程。
对于CPU绑定的任务,使用多线程实际上会下降性能。
对于CPU绑定的任务,使用多处理能够提升性能。