感受沒有GIL鎖的Python3
GIL全局解釋器鎖
????????GIL(Global Interpreter Lock)保證在CPython進(jìn)程中,只有一個(gè)線程執(zhí)行字節(jié)碼,甚至在多核CPU的情況下,也是只能允許一個(gè)CPU上的一個(gè)線程在運(yùn)行。
????????由于GIL鎖的存在,Python3的多線程不適合CPU密集型的工作。GIL使得部署Python AI模型變得困難。GIL導(dǎo)致無法充分利用GPU資源。
????????目前PEP 703(python增強(qiáng)建議書)中,針對(duì)GIL對(duì)科學(xué)計(jì)算造成的問題做了詳細(xì)的描述,有興趣的可以去看看:https://peps.python.org/pep-0703/。

????????目前社區(qū)中對(duì)于移除GIL鎖的呼聲也越來越高了,也不乏有大神將GIL鎖給移除了,下面就根據(jù)大神的沒有GIL鎖的Pyhton來感受一下它的性能。為了有對(duì)比,先來有GIL鎖的通用python版本運(yùn)行多線程看看性能。
設(shè)備配置:
????????操作系統(tǒng):CentOS 7
????????CPU:Intel(R) Xeon(R) E-2224 CPU @ 3.40GHz? ?4核
????????內(nèi)存:32G
通用代碼:CPU密集型多線程代碼
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@文件? ? ? ? :threading-test.py
@說明? ? ? ? : 多線程CPU密集型測(cè)試。
@時(shí)間? ? ? ? :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()
# 計(jì)算? 多線程執(zhí)行
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

執(zhí)行結(jié)果:最終運(yùn)行178s。

????????根據(jù)上述運(yùn)行圖可知,由于GIL鎖的存在,5個(gè)線程在4個(gè)核心之間來回切換,使得CPU負(fù)載只能到100。
2、沒有GIL鎖的python性能展示
項(xiàng)目地址:https://github.com/colesbury/nogil
通過啟用docker來展示。代碼還用一樣的代碼。設(shè)備還是一樣的設(shè)備。
2.1、下載docker鏡像
docker pull nogil/python
2.2、運(yùn)行docker鏡像
docker run -it --rm nogil/python
2.3、進(jìn)入鏡像,并運(yùn)行代碼

docker exec -it 51d256330bed /bin/bash? ? # 進(jìn)入容器
由于鏡像中沒有vi和vim,用scp將代碼從物理機(jī)copy到容器中。
scp root@192.168.90.111:/root/threading-test.py ./
root@51d256330bed:/# python3 threading-test.py

執(zhí)行結(jié)果:最終運(yùn)行81s。

????????根據(jù)上述運(yùn)行圖可知,由于沒有GIL鎖的存在,5個(gè)線程同時(shí)執(zhí)行,將4個(gè)核心直接拉滿,使得CPU負(fù)載一度達(dá)到了400。同樣的代碼,在有GIL鎖和沒有GIL鎖的環(huán)境下,性能直接提升了1倍。
結(jié)語:
????????GIL鎖的加入,是為了Python多線程的線程安全,就目前來看,在沒有官方出品前,還是要慎用沒有GIL鎖的Python。本人在這之前也測(cè)試過Python 3.12.0a4的版本,(被國(guó)內(nèi)某些標(biāo)題黨誤導(dǎo)的,比如:"Python-3.12 告別 GIL 鎖 & 性能原地飛升!"),該版本目前屬于開發(fā)版,根據(jù)我用上面的代碼實(shí)測(cè),Python?3.12對(duì)多線程的優(yōu)化還是有的,同一臺(tái)設(shè)備,同樣的代碼,不同的python環(huán)境,Python 3.12的多線程也能比Python3.8.16的多線程性能快1倍。但是Python 3.12仍然有GIL鎖,多線程代碼運(yùn)行過程中多核心仍然達(dá)不到100的使用率??偣惨仓挥?00。