关于 Python 的 import,你了解多少?

多线程和多进程是 Python 中两种实现多任务的不同策略,二者都可以在特定的场景下在一定程度上提高程序的运行速度、性能以及吞吐,但二者的运行机制却有很大的差别。

在 Python 中,多线程以_并发(concurrent)的方式运行,适用于 I/O 密集型任务的场景;多进程以并行(parallelism)的方式运行,适用于计算密集型_任务的场景。虽然多进程也可以用于 I/O 密集型任务的场景,但这会导致部分 CPU 性能的浪费,且进程的开销也比线程要高。而多线程用于计算密集型的任务场景则相当于这些任务串行执行。

⒈ GIL(Global Interpreter Lock)
⑴ GIL 介绍

GIL 是一种互斥锁机制,其目的是为了确保在同一时间只有一个线程可以运行,进而确保了在同一时间只有一个线程可以访问/操作内存。但这同时也阻止了 Python 多线程对多核处理器的充分利用。

⑵ 为什么引入 GIL

Python 通过引用计数的方式进行垃圾回收。当一个对象的引用计数降为 0 时,该对象会被垃圾回收,其所占用的内存空间会被释放。

import sysa = []
b = a
print(sys.getrefcount(a)) # 3

上例中,对象 [] 被变量 ab 以及函数 sys.getrefcount() 的参数同时引用,故结果为 3

如果允许同一时间有多个线程同时运行,那么这些线程同时修改对象的引用计数可能会出现竞争条件,最终导致对象的引用计数错误,进而导致程序崩溃(引用计数过早的降为 0)或内存泄漏。

import threadingcount = 0def accumulator():global countfor i in range(0, 100000):count += 1threads = []for i in range(0, 100):threads.append(threading.Thread(target=accumulator))for thread in threads:thread.start()for thread in threads:thread.join()print(count) # 8752687

GIL 只是确保同一时间只有一个线程在执行,但并不一定能阻止竞争条件

⑶ GIL 带来的影响

GIL 使得 Python 多线程无法充分利用多核处理器的优势,进而使得多线程无法适用于计算密集型的场景。

GIL 可能会在 Python 3.13 中设置为可选项

⒉ 多线程

在 Python 中,由于 GIL 机制的限制,同一时间只能有一个线程在执行,这就决定了 Python 的多线程只会对 I/O 密集型任务的性能有显著的提升。

在 I/O 密集型的任务场景中,当一个线程因为等待 I/O 被阻塞时,系统可以将当前线程挂起而执行其他线程,这样可以充分利用 CPU 资源,缩短程序的总体运行时间,提升性能。

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import matplotlib.pyplot as plt
from random import choice
from string import ascii_letters
import timedef multi_threading(func, args, workers):with ThreadPoolExecutor(max_workers=workers) as ex:res = ex.map(func, args)return list(res)def create_text():text = ''.join(choice(ascii_letters) for i in range(10**7))return textdef io_bound(text: str, base: float = 0):start = time.time() - basef = open('letters.txt', 'wt', encoding='utf-8')f.write(text)end = time.time() - basereturn start, enddef visualize_performance(times: list, workers: list):figure, axe = plt.subplots(layout='constrained')figure.suptitle('io bound tasks: more threads, less time')axe.set_xlabel('number of threads')axe.set_ylabel("time used (s)")axe.bar(workers, times)plt.show()texts = [create_text() for i in range(16)]
workers_num = [1, 2, 4, 8, 16]
times = []
for num in workers_num:start = time.time()res = multi_threading(io_bound, texts, num)end = time.time()times.append(end - start)visualize_performance(times, ['1', '2', '4', '8', '16'])

上述代码通过将一个随机生成的包含 10710^7107 个字符的字符串写入文本文件 16 次来模拟 I/O 密集型任务的场景。在程序运行过程中,整体的运行时间会随着线程数量的增加而下降。

Figure_1.png

def multi_threading(func, args, workers):start_time = time.time()with ThreadPoolExecutor(max_workers=workers) as ex:res = ex.map(func, args, [start_time] * len(args))return list(res)def visualize_mechanism(times: list, task_num: int):figure, axe = plt.subplots(layout='constrained')figure.suptitle('io bound tasks with %s threads' % task_num)axe.set_xlabel('seconds')axe.set_ylabel('tasks')widths = [t[1] - t[0] for t in times]lefts = [t[0] for t in times]axe.barh(range(len(times)), widths, left=lefts)plt.show()texts = [create_text() for i in range(16)]
workers_num = [1, 2, 4, 8, 16]
times = []for num in workers_num:res = multi_threading(io_bound, texts, num)visualize_mechanism(res, num)

对之前的代码进行适当的修改,查看多线程的运行机制。当只有一个线程来执行上述文件写入操作时,所有的 16 次文件写入会依次执行,每一次写入都只有等到上一次写入彻底完成后才能开始执行。

Figure_1.png

而在多线程模式下,上述的文件写入操作则会并发执行。

Figure_2.png

Figure_3.png

Figure_4.png

Figure_5.png

对于计算密集型的任务,随着线程数量的增加,任务的执行速度和性能并没有提升。

def cpu_bound(base: float = 0):start = time.time() - basecount = 0for i in range(0, 10**5):count += 1end = time.time() - basereturn start, end

Figure_1.png

⒊ 多进程

Python 中的多进程充分利用了多核处理器的优势,使得多任务可以并行执行。并行执行的任务数越多,程序运行的越快。Python 多进程模式下,每个进程都有各自独立的解释器(interpreter),各个进程的内存空间也相互独立,所以 GIL 机制并不会成为多进程的瓶颈。

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import matplotlib.pyplot as plt
from random import choice
from string import ascii_letters
import time
from math import cos, pidef multi_processing(func, workers):with ProcessPoolExecutor(max_workers=workers) as ex:res = ex.map(func, [0] * 16)return list(res)def cpu_bound(base: float = 0):start = time.time() - basecount = 0for i in range(0, 10**5):count += cos(i * pi)end = time.time() - basereturn start, endworkers_num = [1, 2, 4, 8, 16]
times = []for num in workers_num:start = time.time()res = multi_processing(cpu_bound, num)end = time.time()times.append(end - start)visualize_performance(times, ['1', '2', '4', '8', '16'])

上述代码通过进行 16 次大量数学计算模拟计算密集型任务场景。随着进程数量的增加,刚开始程序的运行会越来越快。但当进程数量超过机器内核数量时(4),程序运行反而会因为进程的切换而变慢。

Figure_1.png

当所有的 16 次计算任务都通过一个进程进行时,这些任务会串行执行;但随着进程数量的增加,同时执行的任务也会增加;当进程数量超过机器的内核数量时,任务可能会因为进程切换而交错执行。

Figure_1.png

Figure_2.png

Figure_3.png

Figure_4.png

Figure_5.png

使用多进程处理 I/O 密集型的任务,程序运行速度会随着进程数量增加而变快,但同样,当进程数量超过内核数量时,程序的运行速度会变慢。

Figure_1.png

---------------------------END---------------------------

▍学习资源推荐

零基础Python学习资源介绍

👉Python学习路线汇总👈
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。(学习教程文末领取哈)
在这里插入图片描述

👉Python必备开发工具👈
在这里插入图片描述

温馨提示:篇幅有限,已打包文件夹,获取方式在:文末

👉Python学习视频600合集👈
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
在这里插入图片描述

👉实战案例👈
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述

👉100道Python练习题👈
检查学习结果。
在这里插入图片描述
👉面试刷题👈
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

资料领取

上述这份完整版的Python全套学习资料已经上传CSDN官方,朋友们如果需要可以微信扫描下方CSDN官方认证二维码输入“领取资料” 即可领取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/300328.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Chapter 1 Basic Concepts of Communication and Communication Systems

1.1 The Concept of Communication communication【通信】:It is the process of using signals to transmit messages containing information in space. To put it simply, communication is the spatial transmission of information【信息的空间传递】Information【信息】…

C语言数组:数据的集合艺术(续)

前言 在上一篇文章中,我们深入探讨了C语言数组的基本概念、操作以及多维数组的应用。今天,我们将继续探索数组的更多高级特性,包括动态内存分配、指针与数组的关系以及数组在实际编程中的应用案例。 一、动态内存分配与数组 在C语言中&…

Unity开发一个FPS游戏之三

在前面的两篇博客中,我已实现了一个FPS游戏的大部分功能,包括了第一人称的主角运动控制,武器射击以及敌人的智能行为。这里我将继续完善这个游戏,包括以下几个方面: 增加一个真实的游戏场景,模拟一个废弃的…

数据加密的两种方案

说明:本文介绍对项目中的数据加密的两种方案; 场景 源自真实的项目需求,需要我们对系统中的敏感数据(如手机号、证件号等)进行加密处理,即存入到数据库中的是加密后的密文数据。加密本身是不难的&#xf…

Spring Security——11,自定义权限校验方法

自定义权限校验方法 一键三连有没有捏~~ 我们也可以定义自己的权限校验方法,在PreAuthorize注解中使用我们的方法。 自定义一个权限检验方法: 在SPEL表达式中使用 ex相当于获取容器中bean的名字未ex的对象。然后再调用这个对象的 hasAuthority方法&am…

软考高级架构师:嵌入式系统的内核架构

作者:明明如月学长, CSDN 博客专家,大厂高级 Java 工程师,《性能优化方法论》作者、《解锁大厂思维:剖析《阿里巴巴Java开发手册》》、《再学经典:《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

ssm028蜀都天香酒楼的网站设计与实现+jsp

基于JSP的蜀都天香酒楼管理系统的设计与实现 摘要 近年来,信息化管理行业的不断兴起,使得人们的日常生活越来越离不开计算机和互联网技术。首先,根据收集到的用户需求分析,对设计系统有一个初步的认识与了解,确定蜀都…

带头双向循环链表实现

1.结构及特性 前面我们实现了无头单向非循环链表,它的结构是这样的: 在这里的head只是一个指向头结点的指针,而不是带头链表的头节点。 而带头双向循环链表的逻辑结构则是这样的 这就是链表的结构,链表的每一个节点都有两个指针…

docker 安装redis报错:can not init background jbos

启动redis,发现一直再重启 docker run -d --name redis -p 6379:6379 --restartalways redis:6.2.6 --requirepass "123456" 查看日志,发现job没启动 docker logs 47f6572a779c 尝试了一堆解决办法。。。最后发现尝试安装了redis6.2.6版本&a…

从《布瓦尔与佩库歇》实践中学习社会科学概论

从《布瓦尔与佩库歇》实践中学习社会科学概论 前情提要《布瓦尔与佩库歇》实践笔记云藏山鹰社会科学概论报告核心--信息形数身知™意合™意气实体过程意气实体过程宇宙学诠释™ 社会科学概论花间流风版导读,马斯克风格演讲[ 一尚韬竹团队供稿;] 内容展开…

实验4 层次图和HIPO图

一、实验目的 通过绘制层次图和HIPO图,熟练掌握层次图和HIPO图的基本原理。 能对简单问题进行层次图和HIPO图的分析,独立地完成层次图和HIPO图设计。 二、实验项目内容(实验题目) 1、用Microsoft Visio绘制出图书馆管理系统的层…

Flume 拦截器概念及自定义拦截器的运用

文章目录 Flume 拦截器拦截器的作用拦截器运用1.创建项目2.实现拦截器接口3.编写事件处理逻辑4.拦截器构建5.打包与上传6.编写配置文件7.测试运行 Flume 拦截器 在 Flume 中,拦截器(Interceptors)是一种可以在事件传输过程中拦截、处理和修改…

Spring定义Bean对象笔记(二)

前言:上一篇记录了通过XML文件来定义Bean对象,这一篇将记录通过注解和配置类的方式来定义Bean对象。 核心注解: 定义对象:Component,Service,Repository,Controller 依赖注入: 按类型:Autowired 按名称&am…

【JavaScript】作用域 ③ ( JavaScript 作用域链 | 作用域链变量查找机制 )

文章目录 一、JavaScript 作用域链1、作用域2、作用域链3、作用域链变量查找机制 二、代码示例 - 作用域链 一、JavaScript 作用域链 1、作用域 在 JavaScript 中 , 任何代码都有 作用域 , 全局作用域 : 在 <script> 标签中 或者 js 脚本中 定义的变量 属于 全局作用域 …

Vue3【进阶】

简介 https://cn.vuejs.org/guide/introduction.html 创建vue3工程 【基于 vue-cli创建】 基本和vue-cli的过程类似&#xff0c;只是选择的时候用vue3创建 【基于vite创建】【推荐】 【官网】https://vitejs.cn/ 【可以先去学一下webpack】 步骤 【https://cn.vitejs.…

kubernetes集群添加到jumpserver堡垒机里管理

第一步、在kubernetes集群中获取一个永久的token。 jumpserver堡垒机用api的来管理kubernetes&#xff0c;所以需要kubernetes的token&#xff0c;这个token还需要是一个永久的token&#xff0c;版本变更&#xff1a;Kubernetes 1.24基于安全方面的考虑&#xff08;特性门控Le…

LeetCode-热题100:118. 杨辉三角

题目描述 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输入: numRows 1 输出: [[1]]…

代码随想录第32天|455.分发饼干 376. 摆动序列

理论基础 贪心算法核心&#xff1a;选择每一阶段的局部最优&#xff0c;从而达到全局最优。 455.分发饼干 455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09;代码随想录 (programmercarl.com)455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09; 贪心算法理论基础&am…

【AI绘画/作图】风景背景类关键词模板参考

因为ds官网被墙,所以翻了IDE的源码整理了下stablestudio里的官方模板&#xff0c;顺便每个模板生成了一份…不知道怎么写关键词的可以参考 Stunning sunset over a futuristic city, with towering skyscrapers and flying vehicles, golden hour lighting and dramatic cloud…

C语言高效的网络爬虫:实现对新闻网站的全面爬取

1. 背景 搜狐是一个拥有丰富新闻内容的网站&#xff0c;我们希望能够通过网络爬虫系统&#xff0c;将其各类新闻内容进行全面地获取和分析。为了实现这一目标&#xff0c;我们将采用C语言编写网络爬虫程序&#xff0c;通过该程序实现对 news.sohu.com 的自动化访问和数据提取。…