python多线程对多核cpu的利用解析
作者:挪威的森林s 发布时间:2023-03-10 02:50:13
引言
我们经常听到"因为GIL的存在,python的多线程不能利用多核CPU",现在我们暂且不提GIL,python能不能利用多核cpu,今天我做了一个实验,代码很简单如下所示
while 1:
pass
没有运行这段代码前cpu状态
运行之后的状态
下面两张图是运行之后的状态,当然这只是两张比较有代表性的图,截图间隔有十几秒的样子
根据第一张图我们发现cpu1、cpu3的负载有明显增长,我们可以得出python线程是可以利用多核cpu的结论,之前一直以为python运行后会绑定cpu其中的一个核心现在看来并不是这个样子。第二张图就比较有意思了cpu2满载了,这又是为什么呢?
想来想去应该是linux中cpu对进程的亲和性导致的,这种亲和性是软性的并不是强制的,这也就解释了为什么第一张图中是多cpu在负载。
ok为了更直观的看出python线程能够利用多核cpu,我们改下代码,换一种方式再来看下
import os
while 1:
print os.getpid() # 输出进程号
运行代码结果
一目了然,线程的确在不同的核心上切换。
现在我们回过头看下那句经典的话"因为GIL的存在,python的多线程不能利用多核CPU",这句话很容易让人理解成GIL会让python在一个核心上运行,有了今天的例子我们再来重新理解这句话,GIL的存在让python在同一时刻只能有一个线程在运行,这毋庸置疑,但是它并没有给线程锁死或者说指定只能在某个cpu上运行,另外我需要说明一点的是GIL是与进程对应的,每个进程都有一个GIL。
python线程的执行流程理解
线程 ——>抢GIL——>CPU
这种执行流程导致了CPU密集型的多线程程序虽然能够利用多核cpu时跟单核cpu是差不多的,并且由于多个线程抢GIL这个环节导致运行效率<=单线程。
看到这可能会让人产生一种错觉,有了GIL后python是线程安全的,好像根本不需要线程锁,而实际情况是线程拿到CPU资源后并不是一直执行的,python解释器在执行了该线程100条字节码(注意是字节码不是代码)时会释放掉该线程的GIL,如果这时候没有加锁那么其他线程就可能修改该线程用到的资源;
遇到IO也会释放GIL
另外一个问题是遇到IO也会释放GIL,下面是这两种情况的例子
import threading
a = []
def m1():
for _ in range(100000):
a.append(1)
def m2():
for _ in range(100000):
a.append(2)
def check():
"""
检查a是否有序
"""
for i in range(len(a)):
if i != 0:
if a[i] < a[i-1]:
print a[i-1], a[i]
return False
return True
t1 = threading.Thread(target=m1)
t2 = threading.Thread(target=m2)
t1.start()
t2.start()
t1.join()
t2.join()
print check()
预期1111...22222...,截图显示跟预期的不同
import threading
text1 = '1' * 10000
text2 = '2' * 10000
def write(text):
with open('test.txt', 'a') as f:
f.write(text)
def m1():
write(text1)
def m2():
write(text2)
t1 = threading.Thread(target=m1)
t2 = threading.Thread(target=m2)
t1.start()
t2.start()
t1.join()
t2.join()
test.txt截图
最后结论是,因为GIL的存在,python的多线程虽然可以利用多核CPU,但并不能让多个核同时工作。
来源:https://www.jianshu.com/p/48dfd429525d


猜你喜欢
- 一.使用库说明Golang中连接kafka可以使用第三方库:github.com/Shopify/sarama二.Kafka Produce
- django的表单系统,分2种基于django.forms.Form的所有表单类的父类基于django.forms.ModelForm,可以
- 怎样压缩sql server2000的数据库备份文件,像rar一样?小弟有一7m的sql server2000 数据库备
- 安 * oostpython调用C/C++的方法有很多,本文使用boost.python。考虑到后期有好多在boost上的开发工作,所以boo
- 最近有需求是,需要把对方提供的ftp地址上的图片获取到本地服务器,原先计划想着是用shell 操作,因为shell 本身也支持ftp的命令
- 单例模式是一种常见的设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派
- 导语:你不知道Python也能去除“背景”嘛?修饰图片中的头发是设计师最烦人的任务之一!要修得完美,
- 1.获取当前时间var myDate = new Date();2.获取时间中的年月日时分秒myDate.getYear();
- 目录1、几个概念2、举个例子3、解决问题4、换个方法通常,当我们需要对对象的敏感属性或者不希望外部直接访问的属性进行私有化,但是某些时候我们
- 在一开始接触PHP接触MYSQL的时候就听不少人说:“MySQL就跑跑一天几十万IP的小站还可以,要是几百万IP就不行了
- 测试平台 Ubuntu 13.04 X86_64 Python 2.7.4花了将近两个小时, 问题主要刚开始没有想到传一个文件对象到线程里面
- Oracle数据库以其高可靠性、安全性、可兼容性,得到越来越多的企业的青睐。如何使Oracle数据库保持优良性能,这是许多数据库管理员关心的
- BootStrap模态框简单概述Bootstrap Modals(模态框)是使用定制的 Jquery 插件创建的。它可以用来创建模态窗口丰富
- 0.摘要在Python中,尤其是数组当中,对于一些异常值往往需要进行特殊处理。为了防止异常值与正常数据混淆,影响最终计算结果,常用的方法是将
- 背景借助django-admin,可以快速得到CRUD界面,但若需要创建多选标签字段时,需要对表单进行调整示例model.py一个tag(标
- 前面的python3入门系列基本上也对python入了门,从这章起就开始介绍下python的爬虫教程,拿出来给大家分享;爬虫说的简单,就是去
- 学习 Python 时,尤其是在进行文件操作和数据处理时,经常会处理路径问题。最常用和常见的是 os.path 模块,它将路径当做字符串进行
- 虚拟环境的搭建为什么要使用虚拟环境#1、使不同应用开发环境相互独立2、环境升级不影响其他应用,也不会影响全局的python环境3、防止出现包
- 开发一个文件上传共享网站,曾想使用下面的代码实现文件上传的功能: <form enctype="multipart/form
- 本文实例为大家分享了HTML5 JS压缩图片,并获取图片BASE64编码上传的方法,供大家参考,具体内容如下基本过程1) 调用 FileRe