python多进程和多线程谁更快

  • python3.6
  • threading和multiprocessing
  • 四核+三星250G-850-SSD

自从用多进程和多线程进行编程,一致没搞懂到底谁更快。网上很多都说python多进程更快,因为GIL(全局解释器锁)。但是我在写代码的时候,测试时间却是多线程更快,所以这到底是怎么回事?最近再做分词工作,原来的代码速度太慢,想提速,所以来探求一下有效方法(文末有代码效果图)

这里先来一张程序的结果图,说明线程和进程谁更快


一些定义

并行是指两个或者多个事件在同一时刻发生。并发是指两个或多个事件在同一时间间隔内发生

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个程序的执行实例就是一个进程。


实现过程

而python里面的多线程显然得拿到GIL,执行code,最后释放GIL。所以由于GIL,多线程的时候拿不到,实际上,它是并发实现,即多个事件,在同一时间间隔内发生。

但进程有独立GIL,所以可以并行实现。因此,针对多核CPU,理论上采用多进程更能有效利用资源。


现实问题

在网上的教程里面,经常能见到python多线程的身影。比如网络爬虫的教程、端口扫描的教程。

这里拿端口扫描来说,大家可以用多进程实现下面的脚本,会发现python多进程更快。那么不就是和我们分析相悖了吗?

import sys,threading
from socket import * host = "127.0.0.1" if len(sys.argv)==1 else sys.argv[1]
portList = [i for i in range(1,1000)]
scanList = []
lock = threading.Lock()
print('Please waiting... From ',host) def scanPort(port):
try:
tcp = socket(AF_INET,SOCK_STREAM)
tcp.connect((host,port))
except:
pass
else:
if lock.acquire():
print('[+]port',port,'open')
lock.release()
finally:
tcp.close() for p in portList:
t = threading.Thread(target=scanPort,args=(p,))
scanList.append(t)
for i in range(len(portList)):
scanList[i].start()
for i in range(len(portList)):
scanList[i].join()

谁更快

因为python锁的问题,线程进行锁竞争、切换线程,会消耗资源。所以,大胆猜测一下:

在CPU密集型任务下,多进程更快,或者说效果更好;而IO密集型,多线程能有效提高效率。

大家看一下下面的代码:

import time
import threading
import multiprocessing max_process = 4
max_thread = max_process def fun(n,n2):
#cpu密集型
for i in range(0,n):
for j in range(0,(int)(n*n*n*n2)):
t = i*j def thread_main(n2):
thread_list = []
for i in range(0,max_thread):
t = threading.Thread(target=fun,args=(50,n2))
thread_list.append(t) start = time.time()
print(' [+] much thread start')
for i in thread_list:
i.start()
for i in thread_list:
i.join()
print(' [-] much thread use ',time.time()-start,'s') def process_main(n2):
p = multiprocessing.Pool(max_process)
for i in range(0,max_process):
p.apply_async(func = fun,args=(50,n2))
start = time.time()
print(' [+] much process start')
p.close()#关闭进程池
p.join()#等待所有子进程完毕
print(' [-] much process use ',time.time()-start,'s') if __name__=='__main__':
print("[++]When n=50,n2=0.1:")
thread_main(0.1)
process_main(0.1)
print("[++]When n=50,n2=1:")
thread_main(1)
process_main(1)
print("[++]When n=50,n2=10:")
thread_main(10)
process_main(10)

结果如下:

可以看出来,当对cpu使用率越来越高的时候(代码循环越多的时候),差距越来越大。验证我们猜想


CPU和IO密集型

  1. CPU密集型代码(各种循环处理、计数等等)
  2. IO密集型代码(文件处理、网络爬虫等)

判断方法:

  1. 直接看CPU占用率, 硬盘IO读写速度
  2. 计算较多->CPU;时间等待较多(如网络爬虫)->IO
  3. 请自行百度

参考

为什么在Python里推荐使用多进程而不是多线程?

如何判断进程是IO密集还是CPU密集

搞定python多线程和多进程

Python多线程和多进程谁更快?的更多相关文章

  1. Python 多线程、多进程 (三)之 线程进程对比、多进程

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.多线程与多进 ...

  2. Python 多线程、多进程 (一)之 源码执行流程、GIL

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...

  3. Python 多线程、多进程 (二)之 多线程、同步、通信

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...

  4. python多线程与多进程及其区别

    个人一直觉得对学习任何知识而言,概念是相当重要的.掌握了概念和原理,细节可以留给实践去推敲.掌握的关键在于理解,通过具体的实例和实际操作来感性的体会概念和原理可以起到很好的效果.本文通过一些具体的例子 ...

  5. python多线程与多进程--存活主机ping扫描以及爬取股票价格

    python多线程与多进程 多线程: 案例:扫描给定网络中存活的主机(通过ping来测试,有响应则说明主机存活) 普通版本: #扫描给定网络中存活的主机(通过ping来测试,有响应则说明主机存活)im ...

  6. 基于Windows平台的Python多线程及多进程学习小结

    python多线程及多进程对于不同平台有不同的工具(platform-specific tools),如os.fork仅在Unix上可用,而windows不可用,该文仅针对windows平台可用的工具 ...

  7. python 多线程和多进程

    多线程与多进程 知识预览 一 进程与线程的概念 二 threading模块 三 multiprocessing模块 四 协程 五 IO模型 回到顶部 一 进程与线程的概念 1.1 进程 考虑一个场景: ...

  8. python 多线程、多进程

    一.首先说下多线程.多进程用途及异同点,另外还涉及到队列的,memcache.redis的操作等: 1.在python中,如果一个程序是IO密集的操作,使用多线程:运算密集的操作使用多进程. 但是,其 ...

  9. 搞定python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

随机推荐

  1. python 实例方法,类方法和静态方法

    在学习python代码时,看到有的类的方法中第一参数是cls,有的是self,经过了解得知,python并没有对类中方法的第一个参数名字做限制,可以是self,也可以是cls,不过根据人们的惯用用法, ...

  2. ios 视频拼接/合成

    上面的图说明的是这个混合的过程,下面放代码: - (void)mergeAndExportVideos:(NSArray*)videosPathArray withOutPath:(NSString* ...

  3. org.gradle.api.internal.tasks.DefaultTaskInputs$TaskInputUnionFileCollection cannot be cast to org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection

    转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6709758.html Android Studio导入项目报错: org.gradle.api.inter ...

  4. 手把手视频:万能开源Hawk抓取动态网站

    Hawk是沙漠之鹰历时五年开发的开源免费网页抓取工具(爬虫),无需编程,全部可视化. 自从上次发布Hawk 2.0过了小半年,可是还是有不少朋友通过邮件或者微信的方式询问如何使用.看文档还是不如视频教 ...

  5. 初识bd时的一些技能小贴士

    既然小豆腐如此给力,而且充分的利用主动学习的优势,已经有了迅速脑补,压倒式的优势,不过这只是表面而已,一切才刚刚开始,究竟鹿死谁手,还有待验证. 以上可以看到,小豆腐为什么拼命的要teach我们了么, ...

  6. 基于opencv的车牌识别系统

    前言 学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程. 概述     OpenCV的全称是:Open Source Computer Vision ...

  7. 使用纯CSS方案,解决垂直居中

    CSS是HTML元素的剪刀手,它极度的丰富了web页面的修饰.在众多CSS常见的样式需求中,有一奇葩式的存在[垂直居中],因为不管是从逻辑实现方面还是从正常需求量来讲,这都没理由让这个需求在实践过程中 ...

  8. MySQL 5.7贴心参数之 log_timestamps

    写在前面 使用 MySQL 的过程中,经常会有人碰到这么一个问题,看错误日志.慢查询日志的时候,时间总是和本地时间对不上,差了 8 个小时,这样分析起来就相对麻烦了一些. 新改进 对于不知道是什么原因 ...

  9. 【小瑕疵】在div里插入img后在底部留有缝隙怎么解决

    [本文转载自http://blog.sina.com.cn/s/blog_9fd5b6df01013mld.html] 图片IMG与容器下边界之间有空隙怎么办?这里介绍3中简单的解决方法. 第一,给图 ...

  10. HashMap 构造函数

    HashMap总共提供了三个构造函数 /** * Constructs an empty <tt>HashMap</tt> with the default initial c ...