Python中单线程、多线程和多进程的效率对比实验实例


Posted in Python onMay 14, 2019

python的多进程性能要明显优于多线程,因为cpython的GIL对性能做了约束。

Python是运行在解释器中的语言,查找资料知道,python中有一个全局锁(GIL),在使用多进程(Thread)的情况下,不能发挥多核的优势。而使用多进程(Multiprocess),则可以发挥多核的优势真正地提高效率。

对比实验

资料显示,如果多线程的进程是CPU密集型的,那多线程并不能有多少效率上的提升,相反还可能会因为线程的频繁切换,导致效率下降,推荐使用多进程;如果是IO密集型,多线程进程可以利用IO阻塞等待时的空闲时间执行其他线程,提升效率。所以我们根据实验对比不同场景的效率

操作系统 CPU 内存 硬盘
Windows 10 双核 8GB 机械硬盘

(1)引入所需要的模块

import requests
import time
from threading import Thread
from multiprocessing import Process

(2)定义CPU密集的计算函数

def count(x, y):
  # 使程序完成150万计算
  c = 0
  while c < 500000:
    c += 1
    x += x
    y += y

(3)定义IO密集的文件读写函数

def write():
  f = open("test.txt", "w")
  for x in range(5000000):
    f.write("testwrite\n")
  f.close()
 
def read():
  f = open("test.txt", "r")
  lines = f.readlines()
  f.close()

(4) 定义网络请求函数

_head = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36'}
url = "http://www.tieba.com"
def http_request():
  try:
    webPage = requests.get(url, headers=_head)
    html = webPage.text
    return {"context": html}
  except Exception as e:
    return {"error": e}

(5)测试线性执行IO密集操作、CPU密集操作所需时间、网络请求密集型操作所需时间

# CPU密集操作
t = time.time()
for x in range(10):
  count(1, 1)
print("Line cpu", time.time() - t)
 
# IO密集操作
t = time.time()
for x in range(10):
  write()
  read()
print("Line IO", time.time() - t)
 
# 网络请求密集型操作
t = time.time()
for x in range(10):
  http_request()
print("Line Http Request", time.time() - t)

输出

CPU密集:95.6059999466、91.57099986076355 92.52800011634827、 99.96799993515015
IO密集:24.25、21.76699995994568、21.769999980926514、22.060999870300293
网络请求密集型: 4.519999980926514、8.563999891281128、4.371000051498413、4.522000074386597、14.671000003814697

 (6)测试多线程并发执行CPU密集操作所需时间

counts = []
t = time.time()
for x in range(10):
  thread = Thread(target=count, args=(1,1))
  counts.append(thread)
  thread.start()
 
e = counts.__len__()
while True:
  for th in counts:
    if not th.is_alive():
      e -= 1
  if e <= 0:
    break
print(time.time() - t)

Output: 99.9240000248 、101.26400017738342、102.32200002670288

 (7)测试多线程并发执行IO密集操作所需时间

def io():
  write()
  read()
 
t = time.time()
ios = []
t = time.time()
for x in range(10):
  thread = Thread(target=count, args=(1,1))
  ios.append(thread)
  thread.start()
 
e = ios.__len__()
while True:
  for th in ios:
    if not th.is_alive():
      e -= 1
  if e <= 0:
    break
print(time.time() - t)

Output: 25.69700002670288、24.02400016784668

 (8)测试多线程并发执行网络密集操作所需时间

t = time.time()
ios = []
t = time.time()
for x in range(10):
  thread = Thread(target=http_request)
  ios.append(thread)
  thread.start()
 
e = ios.__len__()
while True:
  for th in ios:
    if not th.is_alive():
      e -= 1
  if e <= 0:
    break
print("Thread Http Request", time.time() - t)

Output: 0.7419998645782471、0.3839998245239258、0.3900001049041748

(9)测试多进程并发执行CPU密集操作所需时间

counts = []
t = time.time()
for x in range(10):
  process = Process(target=count, args=(1,1))
  counts.append(process)
  process.start()
e = counts.__len__()
while True:
  for th in counts:
    if not th.is_alive():
      e -= 1
  if e <= 0:
    break
print("Multiprocess cpu", time.time() - t)

Output: 54.342000007629395、53.437999963760376

 (10)测试多进程并发执行IO密集型操作

t = time.time()
ios = []
t = time.time()
for x in range(10):
  process = Process(target=io)
  ios.append(process)
  process.start()
 
e = ios.__len__()
while True:
  for th in ios:
    if not th.is_alive():
      e -= 1
  if e <= 0:
    break
print("Multiprocess IO", time.time() - t)

Output: 12.509000062942505、13.059000015258789

 (11)测试多进程并发执行Http请求密集型操作

t = time.time()
httprs = []
t = time.time()
for x in range(10):
  process = Process(target=http_request)
  ios.append(process)
  process.start()
 
e = httprs.__len__()
while True:
  for th in httprs:
    if not th.is_alive():
      e -= 1
  if e <= 0:
    break
print("Multiprocess Http Request", time.time() - t)

Output: 0.5329999923706055、0.4760000705718994

 实验结果

CPU密集型操作 IO密集型操作 网络请求密集型操作
线性操作 94.91824996469 22.46199995279 7.3296000004
多线程操作 101.1700000762 24.8605000973 0.5053332647
多进程操作 53.8899999857 12.7840000391 0.5045000315

通过上面的结果,我们可以看到:

多线程在IO密集型的操作下似乎也没有很大的优势(也许IO操作的任务再繁重一些就能体现出优势),在CPU密集型的操作下明显地比单线程线性执行性能更差,但是对于网络请求这种忙等阻塞线程的操作,多线程的优势便非常显著了

多进程无论是在CPU密集型还是IO密集型以及网络请求密集型(经常发生线程阻塞的操作)中,都能体现出性能的优势。不过在类似网络请求密集型的操作上,与多线程相差无几,但却更占用CPU等资源,所以对于这种情况下,我们可以选择多线程来执行

以上所述是小编给大家介绍的Python单线程多线程和多进程效率对比详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
推荐下python/ironpython:从入门到精通
Oct 02 Python
Python中的多重装饰器
Apr 11 Python
python实现中文分词FMM算法实例
Jul 10 Python
python利用不到一百行代码实现一个小siri
Mar 02 Python
tensorflow创建变量以及根据名称查找变量
Mar 10 Python
django 发送手机验证码的示例代码
Apr 25 Python
Python中浅拷贝copy与深拷贝deepcopy的简单理解
Oct 26 Python
Django中更改默认数据库为mysql的方法示例
Dec 05 Python
Flask模板引擎之Jinja2语法介绍
Jun 26 Python
numpy:找到指定元素的索引示例
Nov 26 Python
Pytorch: 自定义网络层实例
Jan 07 Python
Python中过滤字符串列表的方法
Dec 22 Python
Dlib+OpenCV深度学习人脸识别的方法示例
May 14 #Python
Python发展简史 Python来历
May 14 #Python
Python基础知识点 初识Python.md
May 14 #Python
Python应用领域和就业形势分析总结
May 14 #Python
python文件写入write()的操作
May 14 #Python
python时间序列按频率生成日期的方法
May 14 #Python
python的依赖管理的实现
May 14 #Python
You might like
PHP生成唯一的促销/优惠/折扣码(附源码)
2012/12/28 PHP
让CodeIgniter数据库缓存自动过期的处理的方法
2014/06/12 PHP
PHP Web木马扫描器代码分享
2015/09/06 PHP
php事件驱动化设计详解
2016/11/10 PHP
实例讲解YII2中多表关联的使用方法
2017/07/21 PHP
滚动经典最新话题[prototype框架]下编写
2006/10/03 Javascript
如何实现动态删除javascript函数
2007/05/27 Javascript
JS的递增/递减运算符和带操作的赋值运算符的等价式
2007/12/08 Javascript
jquery 防止表单重复提交代码
2010/01/21 Javascript
JS 面向对象之神奇的prototype
2011/02/26 Javascript
浅析Js中的单引号与双引号问题
2013/11/06 Javascript
js控制当再次点击按钮时的间隔时间
2014/06/03 Javascript
jQuery内部原理和实现方式浅析
2015/02/03 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
AngularJs  unit-testing(单元测试)详解
2016/09/02 Javascript
基于js粘贴事件paste简单解析以及遇到的坑
2017/09/07 Javascript
在vue-cli搭建的项目中增加后台mock接口的方法
2018/04/26 Javascript
了解ESlint和其相关操作小结
2018/05/21 Javascript
React 无状态组件(Stateless Component) 与高阶组件
2018/08/14 Javascript
AngularJS修改model值时,显示内容不变的实例
2018/09/13 Javascript
JavaScript学习笔记之基于定时器实现图片无缝滚动功能详解
2019/01/09 Javascript
小程序开发中如何使用async-await并封装公共异步请求的方法
2019/01/20 Javascript
vue中的mescroll搜索运用及各种填坑处理
2019/10/30 Javascript
Python-基础-入门 简介
2014/08/09 Python
在Django中创建动态视图的教程
2015/07/15 Python
python实现验证码识别功能
2018/06/07 Python
python print出共轭复数的方法详解
2019/06/25 Python
python3爬取torrent种子链接实例
2020/01/16 Python
Python操作MongoDb数据库流程详解
2020/03/05 Python
巴塞罗那观光通票:Barcelona Pass
2019/10/30 全球购物
美国购买舞会礼服网站:Couture Candy
2019/12/29 全球购物
资产评估专业大学生求职信
2013/09/29 职场文书
《美丽的南沙群岛》教学反思
2014/04/27 职场文书
食品科学与工程专业毕业生求职信范文
2014/07/21 职场文书
单方离婚协议书范本(2014版)
2014/09/30 职场文书
80后创业总结的9条职场用人思想,记得收藏
2019/08/13 职场文书