python多进程和多线程究竟谁更快(详解)


Posted in Python onMay 29, 2017

python3.6

threading和multiprocessing

四核+三星250G-850-SSD

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

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

python多进程和多线程究竟谁更快(详解)

一些定义

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

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

实现过程

而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)

结果如下:

python多进程和多线程究竟谁更快(详解)

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

CPU和IO密集型

1、CPU密集型代码(各种循环处理、计数等等)

2、IO密集型代码(文件处理、网络爬虫等)

判断方法:

1、直接看CPU占用率, 硬盘IO读写速度

2、计算较多->CPU;时间等待较多(如网络爬虫)->IO

3、请自行百度

以上这篇python多进程和多线程究竟谁更快(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中实现对list做减法操作介绍
Jan 09 Python
python自动格式化json文件的方法
Mar 11 Python
Python实现的rsa加密算法详解
Jan 24 Python
python互斥锁、加锁、同步机制、异步通信知识总结
Feb 11 Python
小白如何入门Python? 制作一个网站为例
Mar 06 Python
python通过微信发送邮件实现电脑关机
Jun 20 Python
Python迭代器与生成器用法实例分析
Jul 09 Python
Python使用sort和class实现的多级排序功能示例
Aug 15 Python
python os.fork() 循环输出方法
Aug 08 Python
Python tornado上传文件的功能
Mar 26 Python
在django中form的label和verbose name的区别说明
May 20 Python
Django创建一个后台的基本步骤记录
Oct 02 Python
python 3利用BeautifulSoup抓取div标签的方法示例
May 28 #Python
Python虚拟环境virtualenv的安装与使用详解
May 28 #Python
python 调用win32pai 操作cmd的方法
May 28 #Python
Python 稀疏矩阵-sparse 存储和转换
May 27 #Python
Django基础之Model操作步骤(介绍)
May 27 #Python
python之PyMongo使用总结
May 26 #Python
Python3安装Pymongo详细步骤
May 26 #Python
You might like
codeigniter自带数据库类使用方法说明
2014/03/25 PHP
php在linux下检测mysql同步状态的方法
2015/01/15 PHP
ThinkPHP表单令牌错误的相关解决方法分析
2016/05/20 PHP
谈谈从phpinfo中能获取哪些值得注意的信息
2017/03/28 PHP
php 删除一维数组中某一个值元素的操作方法
2018/02/01 PHP
jquery实现metro效果示例代码
2013/09/06 Javascript
javascript制作的滑动图片菜单
2015/05/15 Javascript
jQuery绑定事件监听bind和移除事件监听unbind用法实例详解
2016/01/19 Javascript
EXT中单击button按钮grid添加一行(光标位置可设置)的实例代码
2016/06/02 Javascript
JS字符串按逗号和回车分隔的方法
2017/04/25 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
2017/07/13 Javascript
web前端vue之CSS过渡效果示例
2018/01/10 Javascript
JavaScript实用代码小技巧
2018/08/23 Javascript
node使用Mongoose类库实现简单的增删改查
2018/11/08 Javascript
微信小程序实现批量倒计时功能
2020/11/01 Javascript
解决vue-pdf查看pdf文件及打印乱码的问题
2020/11/04 Javascript
手动实现vue2.0的双向数据绑定原理详解
2021/02/06 Vue.js
[01:50]WODOTA制作 DOTA2中文宣传片《HERO》
2013/04/28 DOTA
Python运用于数据分析的简单教程
2015/03/27 Python
利用Celery实现Django博客PV统计功能详解
2017/05/08 Python
关于django 数据库迁移(migrate)应该知道的一些事
2018/05/27 Python
Python 字符串转换为整形和浮点类型的方法
2018/07/17 Python
python微信撤回监测代码
2019/04/29 Python
python实现while循环打印星星的四种形状
2019/11/23 Python
Python模拟键盘输入自动登录TGP
2020/11/27 Python
软件设计的目标是什么
2016/12/04 面试题
单位工程竣工验收方案
2014/03/16 职场文书
《大江保卫战》教学反思
2014/04/11 职场文书
班训口号大全
2014/06/18 职场文书
还款承诺书范本
2015/01/20 职场文书
财产保全担保书
2015/01/20 职场文书
党员年终个人总结
2015/02/14 职场文书
法院个人总结
2015/03/03 职场文书
优秀党员主要事迹材料
2015/11/04 职场文书
Mysql binlog日志文件过大的解决
2021/10/05 MySQL
Python&Matlab实现灰狼优化算法的示例代码
2022/03/21 Python