Python多进程与多线程的使用场景详解
作者:大帅不是我 发布时间:2022-11-21 09:17:37
前言
Python多进程适用的场景:计算密集型(CPU密集型)任务
Python多线程适用的场景:IO密集型任务
计算密集型任务一般指需要做大量的逻辑运算,比如上亿次的加减乘除,使用多核CPU可以并发提高计算性能。
IO密集型任务一般指输入输出型,比如文件的读取,或者网络的请求,这类场景一般会遇到IO阻塞,使用多核CPU来执行并不会有太高的性能提升。
下面使用一台64核的虚拟机来执行任务,通过示例代码来区别它们,
示例1:执行计算密集型任务,进行1亿次运算
使用多进程
from multiprocessing import Process
import os, time
# 计算密集型任务
def work():
res = 0
for i in range(100 * 100 * 100 * 100): # 亿次运算
res *= i
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU") # 本机为64核
start = time.time()
for i in range(4):
p = Process(target=work) # 多进程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("计算密集型任务,多进程耗时 %s" % (stop - start))
使用多线程
from threading import Thread
import os, time
# 计算密集型任务
def work():
res = 0
for i in range(100 * 100 * 100 * 100): # 亿次运算
res *= i
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU") # 本机为64核
start = time.time()
for i in range(4):
p = Thread(target=work) # 多线程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("计算密集型任务,多线程耗时 %s" % (stop - start))
两段代码输出:
本机为 64 核 CPU
计算密集型任务,多进程耗时 6.864224672317505
本机为 64 核 CPU
计算密集型任务,多线程耗时 37.91042113304138
说明:上述代码中,分别使用4个多进程和4个多线程去执行亿次运算,多进程耗时6.86s,多线程耗时37.91s,可见在计算密集型任务场景,使用多进程能大大提高效率。
另外,当分别使用8个多进程和8个多线程去执行亿次运算时,耗时差距更大,输出如下:
本机为 64 核 CPU
计算密集型任务,多进程耗时 6.811635971069336
本机为 64 核 CPU
计算密集型任务,多线程耗时 113.53767895698547
可见在64核的cpu机器下,同时使用8个多进程和4个多进程效率几乎一样。而使用多线程则就效率较慢。要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数
示例2:400次,阻塞两秒,读取文件
使用多进程(4核cpu)
from multiprocessing import Process
import os, time
# I/0密集型任务
def work():
time.sleep(5) # 阻塞两秒
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU")
start = time.time()
for i in range(1000):
p = Process(target=work) # 多进程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("I/0密集型任务,多进程耗时 %s" % (stop - start))
使用多线程(4核cpu)
from threading import Thread
import os, time
# I/0密集型任务
def work():
time.sleep(5) # 阻塞两秒
if __name__ == "__main__":
l = []
print("本机为", os.cpu_count(), "核 CPU")
start = time.time()
for i in range(1000):
p = Thread(target=work) # 多线程
l.append(p)
p.start()
for p in l:
p.join()
stop = time.time()
print("I/0密集型任务,多线程耗时 %s" % (stop - start))
输出:
本机为 64 核 CPU
I/0密集型任务,多进程耗时 12.28218412399292
本机为 64 核 CPU
I/0密集型任务,多线程耗时 5.399136066436768
说明:python的多线程有于GIL锁的存在,无论是多少核的cpu机器,也只能使用单核,从输出结果来看,对于IO密集型任务使用多线程比较占优。
FAQ:执行多进程的io密集型任务时,报了一个错:
OSError: [Errno 24] Too many open files
原因:linux系统限制
ulimit -n
# 输出 1024
解决:(临时提高系统限制,重启后失效)
ulimit -n 10240
总结
来源:https://blog.csdn.net/hhs_1996/article/details/114317308
猜你喜欢
- Pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。Pandas的名称来自于面板数据(pan
- 问题描述:使用指令 python -m pip install --upgrade pip 升级pip时,Pycharm报错:Attribu
- 实验目的:用户输入网卡名称,通过函数返回对应的IPv4和IPv6地址。实验代码:步骤一: 由于window系统下网卡名称并不是真正的名字,而
- 描述:下午快下班的时候公司供应链部门的同事跑过来问我能不能以程序的方法帮他解决一些excel表格每周都需要手工重复做的事情,Excel 是数
- 先给大家介绍下Django打印出在数据库中执行的语句有时我们需要看models操作时对应的SQL语句,可以用如下方法查看---在django
- 如下所示:./src/github.com/sirupsen/logrus/terminal_check_notappengine.go:9
- 在Python里面,使用Pandas里面的DataFrame来存放数据的时候想要把数据集进行shuffle会许多的方法,本文介绍两种比较常用
- 本文实例讲述了Python实现FTP上传文件或文件夹实例。分享给大家供大家参考。具体如下:import sys import os impo
- 一、密码式给数据库起一个随机复杂的名称,避免被猜到被下载,这种方式在以前很流行,因为大家都对自己的代码很有自信。但随着错误提示对数据库地址的
- 前言在搜集了很多文本语料之后,会开始漫长的数据清洗过程,通常要不断迭代。1. 问题描述有些文本数据中,会包含一些特殊符号。猜想可能是从某些富
- 一、PIL库对图像的基本操作1、读取图片PIL网上有很多介绍,这里不再讲解。直接操作,读取一张图片,将其转换为灰度图像,并打印出来。from
- 过年这段时间由于线上数据库经常压力过大导致响应非常缓慢甚至死机,咬咬牙下大决心来解决效率不高的问题!首先是由于公司秉承快速开发原则,频繁上线
- 前言时值毕业季,有不少小伙伴深受论文查重的困扰。因此我便想到做一个简单的自动去重的工具,先看看效果,我们再对原理或是代码实现做进一步的分析。
- 一个 MySQL 表可以看作是一个队列,每一行为一个元素。每次查询得到满足某个条件的最前面的一行,并将它从表中删除或者改变它的状态,使得下次
- 发现一个有意思的现象,labelimg打开图片和xml标签时候,看不到标注好的框框,仔细查看了xml文件,没发现什么异常,后面试一下,才发现
- 上一章节我们学习了如何生成 word 文档以及在文档行中添加各种内容,今天我们基于上一章节的内容进行添砖加瓦 —>
- 阅读《YUI学习笔记(1)》YAHOO.lang.dump 与 YAHOO.lang.substitute。1.&nbs
- 目录0. 前言1. 测试环境及关键代码解释1.1 简单测试环境1.2 关键代码2. 完整代码3. 运行效果4. 报错效果4.1 远程连接不上
- 前言今天就给大家介绍四个你不怎么常用排序函数,他们就是SQL Server排序中经常用到的ROW_NUMBER(),RANK(),DENSE
- MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的。点击进入:下载地址1.下面是msi的下载和安装的步骤点击进去之后根据自己