python多线程效率低_Python 多进程、多线程效率比较
Python 界有条不成文的准则: 计算密集型任务适合多进程,IO 密集型任务适合多线程。本篇来作个比较。
通常来说多线程相对于多进程有优势,因为创建一个进程开销比较大,然而因为在 python 中有 GIL 这把大锁的存在,导致执行计算密集型任务时多线程实际只能是单线程。而且由于线程之间切换的开销导致多线程往往比实际的单线程还要慢,所以在 python 中计算密集型任务通常使用多进程,因为各个进程有各自独立的 GIL,互不干扰。
而在 IO 密集型任务中,CPU 时常处于等待状态,操作系统需要频繁与外界环境进行交互,如读写文件,在网络间通信等。在这期间 GIL 会被释放,因而就可以使用真正的多线程。
以上是理论,下面做一个简单的模拟测试: 大量计算用 math.sin() + math.cos() 来代替,IO 密集型用 time.sleep() 来模拟。 在 Python 中有多种方式可以实现多进程和多线程,这里一并纳入看看是否有效率差异:
多进程: joblib.multiprocessing, multiprocessing.Pool, multiprocessing.apply_async, concurrent.futures.ProcessPoolExecutor
多线程: joblib.threading, threading.Thread, concurrent.futures.ThreadPoolExecutor
from multiprocessing import Pool
from threading import Thread
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time, os, math
from joblib import Parallel, delayed, parallel_backend
def f_IO(a): # IO 密集型
time.sleep(5)
def f_compute(a): # 计算密集型
for _ in range(int(1e7)):
math.sin(40) + math.cos(40)
return
def normal(sub_f):
for i in range(6):
sub_f(i)
return
def joblib_process(sub_f):
with parallel_backend("multiprocessing", n_jobs=6):
res = Parallel()(delayed(sub_f)(j) for j in range(6))
return
def joblib_thread(sub_f):
with parallel_backend('threading', n_jobs=6):
res = Parallel()(delayed(sub_f)(j) for j in range(6))
return
def mp(sub_f):
with Pool(processes=6) as p:
res = p.map(sub_f, list(range(6)))
return
def asy(sub_f):
with Pool(processes=6) as p:
result = []
for j in range(6):
a = p.apply_async(sub_f, args=(j,))
result.append(a)
res = [j.get() for j in result]
def thread(sub_f):
threads = []
for j in range(6):
t = Thread(target=sub_f, args=(j,))
threads.append(t)
t.start()
for t in threads:
t.join()
def thread_pool(sub_f):
with ThreadPoolExecutor(max_workers=6) as executor:
res = [executor.submit(sub_f, j) for j in range(6)]
def process_pool(sub_f):
with ProcessPoolExecutor(max_workers=6) as executor:
res = executor.map(sub_f, list(range(6)))
def showtime(f, sub_f, name):
start_time = time.time()
f(sub_f)
print("{} time: {:.4f}s".format(name, time.time() - start_time))
def main(sub_f):
showtime(normal, sub_f, "normal")
print()
print("------ 多进程 ------")
showtime(joblib_process, sub_f, "joblib multiprocess")
showtime(mp, sub_f, "pool")
showtime(asy, sub_f, "async")
showtime(process_pool, sub_f, "process_pool")
print()
print("----- 多线程 -----")
showtime(joblib_thread, sub_f, "joblib thread")
showtime(thread, sub_f, "thread")
showtime(thread_pool, sub_f, "thread_pool")
if __name__ == "__main__":
print("----- 计算密集型 -----")
sub_f = f_compute
main(sub_f)
print()
print("----- IO 密集型 -----")
sub_f = f_IO
main(sub_f)
结果:
----- 计算密集型 -----
normal time: 15.1212s
------ 多进程 ------
joblib multiprocess time: 8.2421s
pool time: 8.5439s
async time: 8.3229s
process_pool time: 8.1722s
----- 多线程 -----
joblib thread time: 21.5191s
thread time: 21.3865s
thread_pool time: 22.5104s
----- IO 密集型 -----
normal time: 30.0305s
------ 多进程 ------
joblib multiprocess time: 5.0345s
pool time: 5.0188s
async time: 5.0256s
process_pool time: 5.0263s
----- 多线程 -----
joblib thread time: 5.0142s
thread time: 5.0055s
thread_pool time: 5.0064s
上面每一方法都统一创建6个进程/线程,结果是计算密集型任务中速度:多进程 > 单进程/线程 > 多线程, IO 密集型任务速度: 多线程 > 多进程 > 单进程/线程。
/
python多线程效率低_Python 多进程、多线程效率比较相关推荐
- python计算密集型任务_Python多进程和多线程测试比高低,只为证明谁是最快的“仔”
目的 前面分别详细介绍了python的多进程和多线程,如果还没看前面文章的,请先看下之前的文章详解内容.有任何疑问请留言.那这里就不再对多线程和多进程的实现和用法再赘述了.那各位同学学习了python ...
- python并发与并行_python多进程,多线程分别是并行还是并发
匿名用户 1级 2017-09-30 回答 展开全部 并发和并行 你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行. 你吃饭吃到一半,电话来了,你停了下来接了电话, ...
- python 多线程 廖雪峰_python中多线程与多进程中的数据共享问题
之前在写多线程与多进程的时候,因为一般情况下都是各自完成各自的任务,各个子线程或者各个子进程之前并没有太多的联系,如果需要通信的话我会使用队列或者数据库来完成,但是最近我在写一些多线程与多进程的代码时 ...
- python jsonpath效率低_Python学习:jsonpath的性能问题
问题 前面刚总结了,利用jsonpath可以快速访问和设置json对象节点值的帖子.没想到这么快就打脸了.python的jsonpath居然性能如此之差,简直无法接受. 今天其实就是抛一个问题,作为记 ...
- python多线程下载视频_python 实现多线程下载m3u8格式视频并使用fmmpeg合并
电影之类的长视频好像都用m3u8格式了,这就导致了多线程下载视频的意义不是很大,都是短视频,线不线程就没什么意义了嘛. 我们知道,m3u8的链接会下载一个文档,相当长,半小时的视频,应该有接近千行ts ...
- python使用多线程写生成器_Python学习——多线程,异步IO,生成器,协程
Python的语法是简洁的,也是难理解的. 比如yield关键字: def fun(): for i in range(5): print('test') x = yield i print('goo ...
- python函数的定义域_python中多线程的变量定义域问题
最近遇到了一个还算常见的错误提示:local variable 'xxx' referenced before assignment 字面上的意思就是该变量在引用前还未定义,于是我去代码里找到了这个变 ...
- python多线程返回值_python获取多线程及子线程的返回值
最近有个需求,用多线程比较合适,但是我需要每个线程的返回值,这就需要我在threading.Thread的基础上进行封装 import threading class MyThread(threadi ...
- python线程池操作_Python mutiprocessing多线程池pool操作示例
本文实例讲述了Python mutiprocessing多线程池pool操作.分享给大家供大家参考,具体如下: python - mutiprocessing 多线程 pool 脚本代码: root@ ...
最新文章
- 从零开始学习Kafka
- mysql cluster 设置单向复制_mysql5.6做单向主从复制Replication
- cefsharp已停止工作_windows资源管理器已停止工作怎么解决
- python两个二维数组加法_对二维数组的多个列进行Numpy平均
- ios 上传图片到阿里云的oss_JEECG BOOT 上传如何同时支持阿里OSS、Minio、本地存储
- P7599-[APIO2021]雨林跳跃【二分,倍增,ST表】
- axios代理跨域 cli4_跨域本质及解决办法
- K8s遇到问题解决思路
- [jQuery基础] jQuery案例 -- qq音乐以及初步解决Ajax 跨域问题
- RTTI、dynamic_cast、typeid、虚函数表
- TensorFlow之Numpy(3)
- 免费代理ip地址(部分验证过,可使用)
- 第一章计算机视觉引论
- 循迹小车c语言程序51单片机,51单片机循迹小车Proteus仿真程序
- 计算机四级网络工程师(备考过程,避开误区,高效备考!)
- 快半步是天才,快一步是疯子,马云14年前错失一个“微信”?
- 富集分析:(一)概述
- APP推广渠道分析:5种方法和2种思路
- 米家有品这么多好东西哪些值得我们关注
- 未来的无盘网吧是什么样子?
热门文章
- python 进阶公众号_数据分析的进阶之路,不容错过的最全干货公众号
- Vue(八)vue 脚手架、脚手架创建项目示例
- bitdock系统错误_BitDock开机启动失败怎么办?给你两种解决方法
- android 图片作为背景图片,android案例--图片取色并让图片融入背景色
- 数组与字符串相互转换
- org.apache.commons.lang3.StringUtils 的相关用法
- linux chroot函数,chroot()函数 Unix/Linux
- synchronized(this)锁的是什么?同步静态方法,同步非静态方法,锁的都是什么?
- C++ 全局变量定义在哪里合适
- php会员生日祝福,会员生日祝福短信 像花一样芬芳,像梦一样缠绵