欢迎光临散文网 会员登陆 & 注册

感受没有GIL锁的Python3

2023-02-26 22:28 作者:骑驴看数据  | 我要投稿

GIL全局解释器锁

        GIL(Global Interpreter Lock)保证在CPython进程中,只有一个线程执行字节码,甚至在多核CPU的情况下,也是只能允许一个CPU上的一个线程在运行。

        由于GIL锁的存在,Python3的多线程不适合CPU密集型的工作。GIL使得部署Python AI模型变得困难。GIL导致无法充分利用GPU资源。

        目前PEP 703(python增强建议书)中,针对GIL对科学计算造成的问题做了详细的描述,有兴趣的可以去看看:https://peps.python.org/pep-0703/。

Draft(草稿),未被采纳。

        目前社区中对于移除GIL锁的呼声也越来越高了,也不乏有大神将GIL锁给移除了,下面就根据大神的没有GIL锁的Pyhton来感受一下它的性能。为了有对比,先来有GIL锁的通用python版本运行多线程看看性能。

设备配置:

        操作系统:CentOS 7

        CPU:Intel(R) Xeon(R) E-2224 CPU @ 3.40GHz   4核

        内存:32G

通用代码:CPU密集型多线程代码

#!/usr/bin/env python

# -*- encoding: utf-8 -*-

'''

@文件        :threading-test.py

@说明        : 多线程CPU密集型测试。

@时间        :2022/11/22 11:12:04

@作者        :zhide.zhang

'''

import threading

import logging

import datetime

from threading import Event, Semaphore, Barrier

FORMAT = '%(asctime)s %(threadName)s %(thread)d %(message)s'

logging.basicConfig(format=FORMAT,level=logging.INFO)

start = datetime.datetime.now()

# 计算  多线程执行

def calc():

    sum = 0

    for _ in range(1000000000):

        sum += 1

ts = []

for _ in range(5):

    t = threading.Thread(target=calc)

    ts.append(t)

    t.start()

for i in ts:

    i.join()

delta = (datetime.datetime.now()-start).total_seconds()

print(delta)

1、有GIL锁的python性能展示

Python版本:3.8.9

有GIL锁的Python运行负载

执行结果:最终运行178s。

有GIL锁的Python执行结果。

        根据上述运行图可知,由于GIL锁的存在,5个线程在4个核心之间来回切换,使得CPU负载只能到100。

2、没有GIL锁的python性能展示

项目地址:https://github.com/colesbury/nogil

通过启用docker来展示。代码还用一样的代码。设备还是一样的设备。

2.1、下载docker镜像

docker pull nogil/python

2.2、运行docker镜像

docker run -it --rm nogil/python

2.3、进入镜像,并运行代码

查看nogil/python的容器ID

docker exec -it 51d256330bed /bin/bash    # 进入容器

由于镜像中没有vi和vim,用scp将代码从物理机copy到容器中。

scp root@192.168.90.111:/root/threading-test.py ./

root@51d256330bed:/# python3 threading-test.py

没有GIL锁的Python运行负载

执行结果:最终运行81s。

没有GIL锁的Python执行结果。

        根据上述运行图可知,由于没有GIL锁的存在,5个线程同时执行,将4个核心直接拉满,使得CPU负载一度达到了400。同样的代码,在有GIL锁和没有GIL锁的环境下,性能直接提升了1倍。

结语:

        GIL锁的加入,是为了Python多线程的线程安全,就目前来看,在没有官方出品前,还是要慎用没有GIL锁的Python。本人在这之前也测试过Python 3.12.0a4的版本,(被国内某些标题党误导的,比如:"Python-3.12 告别 GIL 锁 & 性能原地飞升!"),该版本目前属于开发版,根据我用上面的代码实测,Python 3.12对多线程的优化还是有的,同一台设备,同样的代码,不同的python环境,Python 3.12的多线程也能比Python3.8.16的多线程性能快1倍。但是Python 3.12仍然有GIL锁,多线程代码运行过程中多核心仍然达不到100的使用率。总共也只有100。


感受没有GIL锁的Python3的评论 (共 条)

分享到微博请遵守国家法律