最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入學(xué)習(xí)python多線程與GIL

 更新時間:2019年08月26日 11:10:50   作者:ybdesire  
這篇文章主要介紹了深入學(xué)習(xí)python多線程與GIL,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

python 多線程效率

在一臺8核的CentOS上,用python 2.7.6程序執(zhí)行一段CPU密集型的程序。

import time
def fun(n):#CPU密集型的程序
  while(n>0):
    n -= 1

start_time = time.time()
fun(10000000)
print('{} s'.format(time.time() - start_time))#測量程序執(zhí)行時間


測量三次程序的執(zhí)行時間,平均時間為0.968370994秒。這就是一個線程執(zhí)行一次fun(10000000)所需要的時間。

下面用兩個線程并行來跑這段CPU密集型的程序。

import time
import threading

def fun(n):
  while(n>0):
    n -= 1

start_time = time.time()
t1 = threading.Thread( target=fun, args=(10000000,) )
t1.start()
t2 = threading.Thread( target=fun, args=(10000000,) )
t2.start()

t1.join()
t2.join()
print('{} s'.format(time.time() - start_time))

測量三次程序的執(zhí)行時間,平均時間為2.150056044秒。

為什么在8核的機(jī)器上,多線程執(zhí)行時間并不比順序執(zhí)行快呢?

再做另一個實(shí)驗(yàn),用下面的命令,把8核cpu中的7個核禁掉。

[xxx]# echo 0 > /sys/devices/system/cpu/cpu1/online
[xxx]# echo 0 > /sys/devices/system/cpu/cpu2/online
[xxx]# echo 0 > /sys/devices/system/cpu/cpu3/online
[xxx]# echo 0 > /sys/devices/system/cpu/cpu4/online
[xxx]# echo 0 > /sys/devices/system/cpu/cpu5/online
[xxx]# echo 0 > /sys/devices/system/cpu/cpu6/online
[xxx]# echo 0 > /sys/devices/system/cpu/cpu7/online

然后在運(yùn)行這個多線程的程序,三次平均時間為2.533491453秒。為什么多線程程序在多核上跑的時間只比單核快一點(diǎn)點(diǎn)呢?

這就要提到python程序多線程的實(shí)現(xiàn)機(jī)制了。

Python多線程實(shí)現(xiàn)機(jī)制

python的多線程機(jī)制,就是用C實(shí)現(xiàn)的真實(shí)系統(tǒng)中的線程。線程完全被操作系統(tǒng)控制。

python內(nèi)部創(chuàng)建一個線程的步驟是這樣的:

  • 創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu)PyThreadState,其中含有一些解釋器狀態(tài)
  • 調(diào)用pthread創(chuàng)建線程
  • 執(zhí)行線程函數(shù)

由于python是解釋形動態(tài)語言,所以在實(shí)現(xiàn)線程時,需要PyThreadState結(jié)構(gòu)來保存一些信息:

  • 當(dāng)前的stack frame (對python代碼)
  • 當(dāng)前的遞歸深度
  • 線程ID
  • 可選的tracing/profiling/debugging hooks

PyThreadState是C語言實(shí)現(xiàn)的一個結(jié)構(gòu)體(摘自[2]):

typedef struct _ts {
  struct _ts *next; # 鏈表指正
  PyInterpreterState *interp; # 解釋器狀態(tài)
  struct _frame *frame; # 當(dāng)前的stack frame
  int recursion_depth; # 當(dāng)前的遞歸深度
  int tracing;
  int use_tracing;
  Py_tracefunc c_profilefunc;
  Py_tracefunc c_tracefunc;
  PyObject *c_profileobj;
  PyObject *c_traceobj;
  PyObject *curexc_type;
  PyObject *curexc_value;
  PyObject *curexc_traceback;
  PyObject *exc_type;
  PyObject *exc_value;
  PyObject *exc_traceback;
  PyObject *dict;
  int tick_counter;
  int gilstate_counter;
  PyObject *async_exc;
  long thread_id; # 線程ID
} PyThreadState;

從目前最新的python源碼中來看,這個結(jié)構(gòu)體中的內(nèi)容已經(jīng)有所改變,但記錄解釋器狀態(tài)的指針PyInterpreterState *interp依然存在。

python解釋器實(shí)現(xiàn)時,用了一個全局變量(_PyThreadState_Current)

[https://github.com/python/cpython/blob/3.1/Python/pystate.c](python3.1和之前的代碼中都存在,python3.2就有所不同了)

PyThreadState *_PyThreadState_Current = NULL;

_PyThreadState_Current指向當(dāng)前執(zhí)行線程的PyThreadState數(shù)據(jù)結(jié)構(gòu)。解釋器通過這個變量,來獲取當(dāng)前所執(zhí)行線程的信息。

python程序中,有一個全局解釋器鎖GIL來控制線程的執(zhí)行,每一個時刻只允許一個線程執(zhí)行。

GIL的行為

GIL最基本的行為只有下面兩個:

  • 當(dāng)前執(zhí)行的線程持有GIL
  • 線程遇到I/O阻塞時,會釋放GIL。(阻塞等待時,就釋放GIL,給另一個線程執(zhí)行的機(jī)會)

那么,如果遇到CPU密集型的線程,一直占用CPU,不會被I/O阻塞,是不是其它線程就沒有機(jī)會執(zhí)行了呢?

非也,為了避免這種情況,解釋器還會周期性的check并執(zhí)行線程調(diào)度。

解釋器周期性check行為,做的就是下面這3件事:

  • 復(fù)位tick計數(shù)器
  • 在主線程中,檢查有沒有需要處理的信號
  • 讓當(dāng)前執(zhí)行線程釋放(Release)GIL,讓其他線程獲取(acquire)GIL并執(zhí)行(給其他線程執(zhí)行的機(jī)會)

而解釋器check的周期,默認(rèn)是100個tick。解釋器的tick并不是基于時間的,每個tick大致相當(dāng)于一條匯編指令的執(zhí)行時間。

從解釋器的check行為中可以看到,只有主線程中會處理信號,子線程中都不處理信號。所以python多線程程序,會給人一種無法處理Ctrl+C的假象,因?yàn)榇蟛糠智闆r下主線程被block住了,無法處理SIGINT信號。

注意python中并沒有實(shí)現(xiàn)線程調(diào)度,python的多線程調(diào)度完全依賴于操作系統(tǒng)。所以python多線程編程中沒有線程優(yōu)先級等概念。

GIL的實(shí)現(xiàn)

python的GIL并不是簡單的用lock實(shí)現(xiàn)的,GIL是用signal實(shí)現(xiàn)的。

  • 線程獲取(acquire)GIL前,先檢查有沒有被free,如果沒有,就sleep等待signal
  • 線程釋放GIL時,還要發(fā)送signal

參考

[1] Understanding the Python GIL.  http://dabeaz.com/python/UnderstandingGIL.pdf

[2] Inside the Python GIL.  http://www.dabeaz.com/python/GIL.pdf

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • keras slice layer 層實(shí)現(xiàn)方式

    keras slice layer 層實(shí)現(xiàn)方式

    這篇文章主要介紹了keras slice layer 層實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • Python代碼閱讀--列表元素邏輯判斷

    Python代碼閱讀--列表元素邏輯判斷

    本篇閱讀的三份代碼的功能分別是判斷列表中的元素是否都符合給定的條件;判斷列表中是否存在符合給定的條件的元素;以及判斷列表中的元素是否都不符合給定的條件,下面小編將在文章里詳細(xì)介紹,需要的朋友可以參考下
    2021-09-09
  • pytorch-RNN進(jìn)行回歸曲線預(yù)測方式

    pytorch-RNN進(jìn)行回歸曲線預(yù)測方式

    今天小編就為大家分享一篇pytorch-RNN進(jìn)行回歸曲線預(yù)測方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • Numpy中arange()的用法及說明

    Numpy中arange()的用法及說明

    Numpy的arange()函數(shù)用于在指定間隔內(nèi)生成均勻間隔的數(shù)組,它接受開始值、停止值和步長來創(chuàng)建數(shù)組,返回的是ndarray類型,如果沒有提供dtype,則會根據(jù)其他參數(shù)推斷數(shù)據(jù)類型,對于浮點(diǎn)類型參數(shù),結(jié)果數(shù)組的長度計算方式為ceil((stop-start)/step)
    2024-10-10
  • Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法的分類

    Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法的分類

    今天給大家整理了Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法的分類的文章,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下
    2021-06-06
  • 將Emacs打造成強(qiáng)大的Python代碼編輯工具

    將Emacs打造成強(qiáng)大的Python代碼編輯工具

    這篇文章主要介紹了將Emacs打造成強(qiáng)大的Python代碼編輯工具的方法,人們常說Vim是編輯器之神而Emacs是神的編輯器:)需要的朋友可以參考下
    2015-11-11
  • Python + OpenCV 實(shí)現(xiàn)LBP特征提取的示例代碼

    Python + OpenCV 實(shí)現(xiàn)LBP特征提取的示例代碼

    這篇文章主要介紹了Python + OpenCV 實(shí)現(xiàn)LBP特征提取的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Pycharm Available Package無法顯示/安裝包的問題Error Loading Package List解決

    Pycharm Available Package無法顯示/安裝包的問題Error Loading Package Li

    這篇文章主要介紹了Pycharm Available Package無法顯示/安裝包的問題Error Loading Package List解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Python3.5 Pandas模塊之Series用法實(shí)例分析

    Python3.5 Pandas模塊之Series用法實(shí)例分析

    這篇文章主要介紹了Python3.5 Pandas模塊之Series用法,結(jié)合實(shí)例形式分析了Python3.5中Pandas模塊的Series結(jié)構(gòu)原理、創(chuàng)建、獲取、運(yùn)算等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2019-04-04
  • Python中的with...as用法介紹

    Python中的with...as用法介紹

    這篇文章主要介紹了Python中的with...as用法介紹,本文直接給出用法實(shí)例,需要的朋友可以參考下
    2015-05-05

最新評論

潜江市| 富锦市| 赤水市| 宁夏| 鄄城县| 泊头市| 扎兰屯市| 夏津县| 绥宁县| 突泉县| 房产| 苗栗县| 江安县| 安阳市| 扬中市| 乌拉特中旗| 呼玛县| 娄烦县| 卢龙县| 岫岩| 德钦县| 五指山市| 台山市| 通河县| 灵石县| 民和| 大竹县| 绥棱县| 钟山县| 会宁县| 沂水县| 五大连池市| 无极县| 通江县| 岳阳市| 平凉市| 常熟市| 方城县| 台北县| 开化县| 织金县|