0):n-=1start_time=time.time()fun(10000000)print('{}s'.format(time.time()-start_time))#測量程序執行時間測量三次程序的執行時間,平均時間為0.968370994秒。這就是一個線程執行一次fun(" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

深入學習python多線程與GIL

系統 1695 0

python 多線程效率

在一臺8核的CentOS上,用python 2.7.6程序執行一段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))#測量程序執行時間
          


測量三次程序的執行時間,平均時間為0.968370994秒。這就是一個線程執行一次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))
          

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

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

再做另一個實驗,用下面的命令,把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
          

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

這就要提到python程序多線程的實現機制了。

Python多線程實現機制

python的多線程機制,就是用C實現的真實系統中的線程。線程完全被操作系統控制。

python內部創建一個線程的步驟是這樣的:

  • 創建一個數據結構PyThreadState,其中含有一些解釋器狀態
  • 調用pthread創建線程
  • 執行線程函數

由于python是解釋形動態語言,所以在實現線程時,需要PyThreadState結構來保存一些信息:

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

PyThreadState是C語言實現的一個結構體(摘自[2]):

            
typedef struct _ts {
  struct _ts *next; # 鏈表指正
  PyInterpreterState *interp; # 解釋器狀態
  struct _frame *frame; # 當前的stack frame
  int recursion_depth; # 當前的遞歸深度
  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源碼中來看,這個結構體中的內容已經有所改變,但記錄解釋器狀態的指針PyInterpreterState *interp依然存在。

python解釋器實現時,用了一個全局變量(_PyThreadState_Current)

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

            
PyThreadState *_PyThreadState_Current = NULL;
          

_PyThreadState_Current指向當前執行線程的PyThreadState數據結構。解釋器通過這個變量,來獲取當前所執行線程的信息。

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

GIL的行為

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

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

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

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

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

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

而解釋器check的周期,默認是100個tick。解釋器的tick并不是基于時間的,每個tick大致相當于一條匯編指令的執行時間。

從解釋器的check行為中可以看到,只有主線程中會處理信號,子線程中都不處理信號。所以python多線程程序,會給人一種無法處理Ctrl+C的假象,因為大部分情況下主線程被block住了,無法處理SIGINT信號。

注意python中并沒有實現線程調度,python的多線程調度完全依賴于操作系統。所以python多線程編程中沒有線程優先級等概念。

GIL的實現

python的GIL并不是簡單的用lock實現的,GIL是用signal實現的。

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

參考

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

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久久久免费观看 | 久草在线免费新视频 | 国产99页 | 玖玖福利 | 在线成人av观看 | 啪啪在线 | 欧美18xxxx | 毛片搜索| 奇米4色| 黄色网页免费 | 亚洲精品资源 | 久久99亚洲综合精品首页 | 午夜精品久久久久久久99黑人 | 国产短视频精品区第一页 | 日本一区二区三区免费高清在线 | 国产夜色福利院在线观看免费 | 无码AV免费一区二区三区A片 | 亚洲一区二区av | 中文字幕av一区二区三区 | 美女扣下面流白浆丝袜 | 国产精品福利短视在线播放频 | 婷婷久久无码欧美人妻 | 成人高清视频免费观看 | 国产欧美日韩在线观看 | 午夜影视大全 | 狠狠色狠狠色综合久久第一次 | 日本特级黄色录像 | 欧美日韩无线码免费播放 | 久久精品伊人 | 黄色国产视频 | 欧美日韩精品一区二区在线播放 | ab毛片| 天天摸夜夜摸夜夜狠狠摸 | 久久久久久免费一区二区三区 | 精品国产午夜福利在线观看 | 日韩2区 | 一级毛片免费视频 | 国产美女被爽到高潮免费A片小说 | 日韩和的一区二在线 | 91久久青青草原免费 | 免费黄色av|