目的

前面分别详细介绍了python的多进程和多线程,如果还没看前面文章的,请先看下之前的文章详解内容。有任何疑问请留言。那这里就不再对多线程和多进程的实现和用法再赘述了。那各位同学学习了python的多线程和多进程,那么到底是多进程有优势呢?还是多线程比较快呢?他们两个哪个运行比较快呢?在代码编程时到底是用多进程呢,还是用多线程呢,如何最优选择呢?本篇文章就让我们讨论下python多进程和多线程的应用场景选择和最优选问题。

python最优选

进程快的佐证测试

当你理解了多线程和多进程后,你是否有过这样的疑问,它们两个到底谁更快呢?网上很多都会说那肯定是多进程更快了,因为线程中GIL(全局解释器锁)存在,实际上是串行执行的,同一时刻只能有一个线程再跑,而进程是相互独立,多个进程是同时执行的。那么,到底是不是这样的呢?我们通过测试一探究竟。

带着上面的疑问进行了测试,根据测试结果图,我们不难看出线程和进程到底哪个快,哪个效率高了。

线程和进程对比图

那么根据上图的测试结果,可以看出进程耗时比较少,线程耗时较多,那说明线程没有进程快,似乎证实了网上很多人的想法呢。但真是这样吗?

线程快的佐证测试

我们都知道:python中的多线程需要先拿到GIL,才能执行代码,然后释放GIL。所以由于GIL的存在,实际上它的并发,即多个事件在同一时间是间隔的。而进程有独立GIL,可以并行实现。因此,针对多核CPU,理论上采用多进程更能有效利用资源,效率更高,耗时更少。但是现实问题是,很多教程中经常能见到python多线程的身影。尤其是:网络爬虫、端口扫描等教程中。这是为什么呢,难道这些教程都是骗人的,写教程的人都是傻子吗?显然不是,认为别人傻的人才是真的傻呢。那么又是问什么呢?

这里举端口扫描的例子来说吧,代码如下:

import sys,threadingfrom 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 timeimport threadingimport multiprocessing max_process = 4max_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密集型场景下,多线程更有优势。

结论

根据上面的测试,我们得到如下结论:

在CPU密集型场景中(如:各种循环处理、计数等等),适合用多进程;

在IO密集型场景中(如:文件处理、网络爬虫等),适合用多线程。

方法选择

那么有同学看到上面的结论就明白了,多进程和多线程的效率快慢,不是始终不变的,是要应对不通场景的,不一样的场景,用不同的方法,这才是正确的选择。那么cpu密集型场景和io密集型场景我怎么区分和判断呢,只有知道当前是何场景,才能做出最优的选择。下面我就教大家来分辨场景。

简单的办法

直接看CPU的占用率或磁盘的IO读写速度。

归纳为:计算较多就是为CPU密集型;时间等待较多(如网络爬虫)就是IO密集型。

下面是测试代码,各位同学不妨自己手动测测,来让自己有更深层的认识。

#coding=utf-8import sysimport multiprocessingimport timeimport threading​​# 定义全局变量Queueg_queue = multiprocessing.Queue()​def init_queue():    print("init g_queue start")    while not g_queue.empty():        g_queue.get()            for _index in range(10):        g_queue.put(_index)    print("init g_queue end")    return​# 定义一个IO密集型任务:利用time.sleep()​def task_io(task_id):    print("IOTask[%s] start" % task_id)    while not g_queue.empty():        time.sleep(1)        try:            data = g_queue.get(block=True, timeout=1)            print("IOTask[%s] get data: %s" % (task_id, data))        except Exception as excep:            print("IOTask[%s] error: %s" % (task_id, str(excep)))    print("IOTask[%s] end" % task_id)    return​g_search_list = list(range(10000))# 定义一个计算密集型任务:利用一些复杂加减乘除、列表查找等def task_cpu(task_id):    print("CPUTask[%s] start" % task_id)    while not g_queue.empty():        count = 0        for i in range(10000):            count += pow(3*2, 3*2) if i in g_search_list else 0        try:            data = g_queue.get(block=True, timeout=1)            print("CPUTask[%s] get data: %s" % (task_id, data))        except Exception as excep:            print("CPUTask[%s] error: %s" % (task_id, str(excep)))    print("CPUTask[%s] end" % task_id)    return task_id​if __name__ == '__main__':    print("cpu count:", multiprocessing.cpu_count(), "")    print(u"========== 直接执行IO密集型任务 ==========")    init_queue()    time_0 = time.time()    task_io(0)    print(u"结束:", time.time() - time_0, "")​    print("========== 多线程执行IO密集型任务 ==========")    init_queue()    time_0 = time.time()    thread_list = [threading.Thread(target=task_io, args=(i,)) for i in range(10)]​    for t in thread_list:        t.start()​    for t in thread_list:        if t.is_alive():            t.join()    print("结束:", time.time() - time_0, "")​    print("========== 多进程执行IO密集型任务 ==========")    init_queue()    time_0 = time.time()    process_list = [multiprocessing.Process(target=task_io, args=(i,)) for i in range(multiprocessing.cpu_count())]​    for p in process_list:        p.start()​    for p in process_list:        if p.is_alive():            p.join()    print("结束:", time.time() - time_0, "")​    print("========== 直接执行CPU密集型任务 ==========")    init_queue()    time_0 = time.time()    task_cpu(0)    print("结束:", time.time() - time_0, "")​    print("========== 多线程执行CPU密集型任务 ==========")    init_queue()    time_0 = time.time()    thread_list = [threading.Thread(target=task_cpu, args=(i,)) for i in range(10)]​    for t in thread_list:        t.start()​    for t in thread_list:        if t.is_alive():            t.join()​    print("结束:", time.time() - time_0, "")​    print("========== 多进程执行cpu密集型任务 ==========")    init_queue()    time_0 = time.time()    process_list = [multiprocessing.Process(target=task_cpu, args=(i,)) for i in range(multiprocessing.cpu_count())]​    for p in process_list:        p.start()​    for p in process_list:        if p.is_alive():            p.join()​    print("结束:", time.time() - time_0, "")

谢谢大家的阅读,如果你有任何疑问和想法,请关注留言评论,第一时间为你解答心中疑惑。

python计算密集型任务_Python多进程和多线程测试比高低,只为证明谁是最快的“仔”相关推荐

  1. python并发与并行_python多进程,多线程分别是并行还是并发

    匿名用户 1级 2017-09-30 回答 展开全部 并发和并行 你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行. 你吃饭吃到一半,电话来了,你停了下来接了电话, ...

  2. python多线程效率低_Python 多进程、多线程效率比较

    Python 界有条不成文的准则: 计算密集型任务适合多进程,IO 密集型任务适合多线程.本篇来作个比较. 通常来说多线程相对于多进程有优势,因为创建一个进程开销比较大,然而因为在 python 中有 ...

  3. python多线程多进程多协程_python 多进程、多线程、协程

    1.python的多线程 多线程就是在同一时刻执行多个不同的程序,然而python中的多线程并不能真正的实现并行,这是由于cpython解释器中的GIL(全局解释器锁)捣的鬼,这把锁保证了同一时刻只有 ...

  4. python io密集 多线程_python多进程和多线程究竟谁更快(详解)

    python3.6 threading和multiprocessing 四核+三星250G-850-SSD 自从用多进程和多线程进行编程,一致没搞懂到底谁更快.网上很多都说python多进程更快,因为 ...

  5. python学习笔记(二十三) -- 多进程和多线程

    目录 多线程多进程的意义 多进程的使用 方式一(fork):  只能在Unix/Linux/Mac系统下执行,windows不可以 方式二(multiprocessing.Process): 全平台通 ...

  6. python线程池并发_python 并发编程多线程之进程池/线程池

    一.验证GIL锁的存在 Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行.虽然 Python 解释器中可以"运行"多个线程,但在任意时刻只有一个线程在解释器中运行 ...

  7. python多程优化_Python 基本功: 13. 多线程运算提速

    小编在前两天开通了一个 Python 金融的专栏,顺便用 TuShare 下载了几只 A股的数据,有兴趣的小伙伴可以去看一下: 多多教Python:Python 金融: TuShare API 获取股 ...

  8. Python第十二章-多进程和多线程01-多进程

    多进程和多线程 一.进程 1.1 进程的引入 现实生活中,有很多的场景中的事情是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的:试想,如果把唱歌和跳舞这2件事情分开依次 ...

  9. python计算密集型提速_利用Cython加速计算密集型python任务

    何为计算密集型任务 下面贴上网上找到的描述计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率.对视频进行高清解码等等,全靠CPU的运算能力.这种计算密集型任务虽然也可以用多任务完成 ...

最新文章

  1. C语言中将绝对地址转换为函数指针以及跳转到内存指定位置处执行的技巧
  2. javaScript 实现多选框全选/反选及批量删除
  3. 通过 ANE(Adobe Native Extension) 启动Andriod服务 推送消息(二)
  4. MiniDao 比Mybatis还灵活实用的J2EE 持久层轻量级解决方案
  5. 大数据分析实战-信用卡欺诈检测
  6. Git使用六:版本对比
  7. 微型计算机原理及应用程序题,微型计算机原理及应用试题及答案
  8. python对文件操作方法是_Python文件操作
  9. ai形状生成工具机器人_一名大学生使用一种语言生成AI工具来创建病毒博客文章...
  10. 还不错的微信活码程序源码+功能强大
  11. 物理建模钢琴-Modartt Pianoteq Pro v6.7.0 WiN
  12. WEBRTC需要,配置自己的 TURN/STUN 服务
  13. 转载的 C#.NET面试题
  14. NOIP是什么?全国青少年信息学奥林匹克联赛各区特派员联系名单大全!
  15. 2022-2028年全球及中国斯特林发动机行业投资前景分析
  16. 苹果企业签名证书制作详解
  17. 开关电源的 PCB 布线设计,电容并联,环路面积
  18. PHP RSA加密解密
  19. 异形3×3魔方还原教程_五分钟教你轻松还原三阶金字塔异形魔方
  20. windows安装scoop教程

热门文章

  1. c语言 define宏名称if(参数),宏编程基础内容
  2. java掠夺_Editing Java版指南/村庄与掠夺 (section)
  3. kubesphere_KubeSphere容器混合云一个人也能轻松运维的K8s
  4. linux-headers,如何升级linux-headers-generic?
  5. yum 更新内核报错 “Error: initscripts conflicts with centos-release-7-0.1406.el7.centos.2.3.x86_64的解决办法
  6. thymeleaf中的条件判断用法
  7. Hibernate--什么是持久化?
  8. Java实现文件复制
  9. html 读取 vb,VB编程:vb读取textbox控件某一行的方法
  10. 基于JAVA+SpringMVC+Mybatis+MYSQL的集市预约管理系统