当前位置: 首页 > news >正文

全局解释器锁 GIL

问题

你已经听说过全局解释器锁 GIL,担心它会影响到多线程程序的执行性能。

解决方案

尽管 Python 完全支持多线程编程,但是解释器的 C 语言实现部分在完全并行执行时并不是线程安全的。

实际上,解释器被一个全局解释器锁保护着,它确保任何时候 都只有一个 Python 线程执行。

GIL 最大的问题就是 Python 的多线程程序并不能利用 多核 CPU 的优势(比如一个使用了多个线程的计算密集型程序只会在一个单 CPU 上 面运行)。

在讨论普通的 GIL 之前,有一点要强调的是 GIL 只会影响到那些严重依赖 CPU 的程序(比如计算型的)。

如果你的程序大部分只会涉及到 I/O,比如网络交互,那么 使用多线程就很合适,因为它们大部分时间都在等待。

实际上,你完全可以放心的创建 几千个 Python 线程,现代操作系统运行这么多线程没有任何压力,没啥可担心的。

而对于依赖 CPU 的程序,你需要弄清楚执行计算的特点。

例如,优化底层算法 要比使用多线程运行快得多。类似的,由于 Python 是解释执行的,如果你将那些性能 瓶颈代码移到一个 C 语言扩展模块中,速度也会提升的很快。

如果你要操作数组,那 么使用 NumPy 这样的扩展会非常的高效。

还有一点要注意的是,线程不是专门用来优化性能的。一个 CPU 依赖型程序可能 会使用线程来管理一个图形用户界面、一个网络连接或其他服务。这时候,GIL 会产生 一些问题,因为如果一个线程长期持有 GIL 的话会导致其他非 CPU 型线程一直等待。

事实上,一个写的不好的 C 语言扩展会导致这个问题更加严重,尽管代码的计算部分 会比之前运行的更快些。

说了这么多,现在想说的是我们有两种策略来解决 GIL 的缺点。

首先,如果你完 全工作于 Python 环境中,你可以使用 multiprocessing 模块来创建一个进程池,并像协同处理器一样的使用。

例如,你有如下的线程代码:

#执行大型计算(CPU限制)

def some_work(args):
...return result

调用上述函数的线程

def some_thread():while True:...r = some_work(args)...修改代码,使用进程池:
pool = None
#执行大型计算(CPU限制)
def some_work(args):return result

调用上述函数的线程

def some_thread():while True:r = pool.apply(some_work, (args))

线程池

if __name__ == '__main__':import multiprocessingpool = multiprocessing.Pool()

这个通过使用一个技巧利用进程池解决了 GIL 的问题。

当一个线程想要执行 CPU 密集型工作时,会将任务发给进程池。然后进程池会在另外一个进程中启动一个单独的 Python 解释器来工作。当线程等待结果的时候会释放 GIL。

并且,由于计算任务在单 独解释器中执行,那么就不会受限于 GIL 了。在一个多核系统上面,你会发现这个技术可以让你很好的利用多 CPU 的优势。

另外一个解决 GIL 的策略是使用 C 扩展编程技术。

主要思想是将计算密集型任务转移给 C,跟 Python 独立,在工作的时候在 C 代码中释放 GIL。

这可以通过在 C 代码中插入下面这串代码来完成:

#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args) {
...
Py_BEGIN_ALLOW_THREADS
...
Py_END_ALLOW_THREADS
...
}

结论

作为一个真实的例子,在多线程的网络编程中神秘 的 stalls 可能是因为其他原因比如一个 DNS 查找延时,而跟 GIL 毫无关系。

最后你需要先去搞懂你的代码是否真的被 GIL 影响到。

同时还要明白 GIL 大部分都应该 只关注 CPU 的处理而不是 I/O.如果你准备使用一个处理器池,注意的是这样做涉及到数据序列化和在不同 Python 解释器通信。

被执行的操作需要放在一个通过 def 语句定义的 Python 函数中, 不能是 lambda、闭包可调用实例等,并且函数参数和返回值必须要兼容 pickle。

C 扩展最重要的特征是它们和 Python 解释器是保持独立的。也就是说,如果你准 备将 Python 中的任务分配到 C 中去执行,你需要确保 C 代码的操作跟 Python 保持独立,这就意味着不要使用 Python 数据结构以及不要调用 Python 的 C API。

也就是说 C 扩展担负起 了大量的计算任务,而不是少数几个计算。

相关文章:

全局解释器锁 GIL

问题 你已经听说过全局解释器锁 GIL,担心它会影响到多线程程序的执行性能。 解决方案 尽管 Python 完全支持多线程编程,但是解释器的 C 语言实现部分在完全并行执行时并不是线程安全的。 实际上,解释器被一个全局解释器锁保护着&#xff…...

github 下载文件加速 https://moeyy.cn/gh-proxy/

GitHub文件链接带不带协议头都可以,支持release、archive以及文件,右键复制出来的链接都是符合标准的。 注意,不支持项目文件夹,请使用Git。 分支源码:https://github.moeyy.xyz/https://github.com/moeyy/project/arc…...

第五章 资源包使用

游戏开发中会大量使用模型文件,图片文件,这些资源都需要事先导入到项目中去。导入的方式非常简单,将这些文件直接复制到项目中的Assets目录下即可。Unity 会在文件添加到 Assets 文件夹时自动检测到这些文件并同步显示在Project视图中。 Uni…...

Linux od命令

Linux od命令用于输出文件内容。 od指令会读取所给予的文件的内容&#xff0c;并将其内容以八进制字码呈现出来。 语法 od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数>][-t <输出格式>][-w <每列字符…...

【15】SCI易中期刊推荐——电子电气 | 仪器仪表(中科院4区)

💖💖>>>加勒比海带<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉 | 深度学习Tr…...

基于PaddleServing的串联部署 ocr 识别模型

要点&#xff1a; 使用paddleserving服务 1 首先需要安装PaddleServing部署相关的环境 PaddleServing是PaddlePaddle推出的一种高性能、易扩展、高可用的机器学习服务框架。PaddleOCR中使用PaddleServing主要是为了将训练好的OCR模型部署到线上环境&#xff0c;提供API服务&a…...

java OutputStream学习

1.概要 OutputStream位于java.io&#xff0c;它在Java 实现的IO类库中是一个很基础的抽象类。在层级上&#xff0c;是所有字节输出流类的父类&#xff0c;在功能上&#xff0c;表示接受字节并把它们输出。 2.实现类及子类简介 OutputStream有诸多子类&#xff1a; ByteAr…...

java 上传文件生成二进制流文件

最近在项目中遇到一个问题&#xff1a;需要将上传的文件生成输出流&#xff0c;然后将输出流转换为输入流上传到oss。 -------------------------------------------导出代码实现---------------------------------------------------------- ByteArrayOutputStream baos nu…...

质量小议22 -- 多少分合适

60分万岁~&#xff1f;&#xff1f;&#xff1f;&#xff01;&#xff01;&#xff01; 如果用分数评价质量&#xff0c;多少分合适&#xff1f;60&#xff0c;70&#xff0c;80...还是100&#xff0c;或者 120 对于质量的提升&#xff0c;是雪中送炭&#xff0c;还是锦上添…...

变频器参数设定说明

使用默贝克MT110-0R4-S2B实现下面的练习题&#xff1a; 1、先恢复出厂设置&#xff0c;再输入电机参数&#xff0c;选择静态调谐 2、两种运行模式&#xff1a;多段速&#xff08;8段&#xff09;和简易PLC&#xff08;4段&#xff09; 3、面板启停&#xff0c;运行模式通过外部…...

实用调试技巧

目录&#xff1a; 1.什么是bug&#xff1f; 2.调试是什么&#xff1f;有多重要&#xff1f; 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 7.编程常见的错误 1.什么是bug&#xff1f; bug--->臭虫、虫子。 为什么含…...

谁是液冷行业真龙头?疯狂的液冷技术!

“人工智能领域AIGC”、“ChatGPT”、“数据特区”、“东数西算”、“数据中心”&#xff0c;可以说是2023年最热的概念&#xff0c;算力提升的背后&#xff0c;处理器的功耗越来越高&#xff0c;想发挥出处理器的最高性能&#xff0c;需要更高的散热效率。 算力井喷之下&…...

自动化运维工具之Ansible

目录 一、自动化运维 1、通过xshell自动化运维 2、Ansible简介 3、Ansible特点及优势 4、Ansible核心程序 5、Ansible工作原理及流程 6、部署Ansible自动化运维工具 7、Ansible常用模块 (1) ansible命令行模块 (2) command模块 (3) shell模块 (4) cron模块 (5) us…...

霍兰德人格分析雷达图

雷达图 Radar Chart 雷达图是多特性直观展示的重要方式 问题分析 霍兰德认为&#xff1a;人格兴趣与职业之间应有一种内在的对应关系 人格分类&#xff1a;研究型、艺术型、社会型、企业型、传统型、现实性 职业&#xff1a;工程师、实验员、艺术家、推销员、记事员、社会工…...

《Odoo开发者模式必知必会》—— 缘起

Odoo作为业界优秀的开源商务软件&#xff0c;在全球范围内拥有广泛的使用者。在领英国际&#xff0c;可以搜索到全球很多国家都有大量odoo人才需求的招聘信息。在国内&#xff0c;虽然已经有为数不少的企业&#xff0c;他们或者已经使用odoo&#xff0c;或者正在了解odoo&#…...

Java8的Options介绍

Java8引入了一个名为 Options 的新类&#xff0c;它是一个容器&#xff0c;可以保存单个值或根本不保存任何值。Optional目的是提供一种更优雅的方式来处理 null 值&#xff0c;这通常会导致NullPointerException。在这篇博客文章中&#xff0c;我们将探索如何在 Java8中使用 O…...

SpringBoot 多数据源及事务解决方案

1. 背景 一个主库和N个应用库的数据源&#xff0c;并且会同时操作主库和应用库的数据&#xff0c;需要解决以下两个问题&#xff1a; 如何动态管理多个数据源以及切换&#xff1f; 如何保证多数据源场景下的数据一致性(事务)&#xff1f; 本文主要探讨这两个问题的解决方案…...

tcpdump使用教程

一、概述 tcpdump是一个功能强大的&#xff0c;用于抓取网络数据包的命令行工具&#xff0c;与带界面的Wireshark一样&#xff0c;基于libpcap库构建。这篇文章主要介绍tcpdump的使用。关于如何使用tcpdump的资料中&#xff0c;最有用的就是tcpdump的两个手册。 tcpdump使用手…...

Zynq-7000、FMQL45T900的GPIO控制(五)---linux应用层配置GPIO输出控制

上文中详细阐述了对应原理图MIO/EMIO的编号&#xff0c;怎么计算获取linux下gpio的编号 本文涉及C代码上传&#xff0c;下载地址 Zynq-7000、FMQL45T900的GPIO控制c语言代码资源-CSDN文库 本文详细记录一下针对获取到gpio的编号&#xff0c;进行配置输出模式&#xff0c;并进…...

带你搞懂人工智能、机器学习和深度学习!

不少高校的小伙伴找我聊入门人工智能该怎么起步&#xff0c;如何快速入门&#xff0c;多长时间能成长为中高级工程师&#xff08;聊下来感觉大多数学生党就是焦虑&#xff0c;毕业即失业&#xff0c;尤其现在就业环境这么差&#xff09;&#xff0c;但聊到最后&#xff0c;很多…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 &#x1f680; 深度解析&#xff1a;etcd 在 Milvus 向量数据库中的关键作用 &#x1f4a1; 什么是 etcd&#xff1f; &#x1f9e0; Milvus 架构简介 &#x1f4e6; etcd 在 Milvus 中的核心作用 &#x1f527; 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...

LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考

目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候&#xff0c;显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...