日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Cython屏蔽GIL锁实践

發(fā)布時(shí)間:2023/12/31 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cython屏蔽GIL锁实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

環(huán)境:

Ubuntu19.10

四核八線程.

題外話,八線程屬于超線程概念,程序員不可控制,屬于操作系統(tǒng)調(diào)度的工作.

基本概念:

什么時(shí)候使用并發(fā)/并行?

資料中有兩種說(shuō)法:

一種是:

涉及到多核就是并行,單核IO異步就是并發(fā)

另一種是:

整個(gè)系統(tǒng)服務(wù)于IO異步任務(wù)就是并發(fā),涉及到CPU密集就是并行

本文以第一種為準(zhǔn)

--------------------------------

消除GIL鎖為什么會(huì)導(dǎo)致單線程變慢?

參考[6]的回答

Python多線程相當(dāng)于單核多線程[7]

--------------------------------

網(wǎng)上資料的多線程包含:

單核多線程和多核多線程.

單核多線程就IO異步.

多核多線程大多數(shù)情況下指的是多核情況.

線程和并發(fā)有關(guān)系,進(jìn)程和隔離有關(guān)系

根據(jù)[4]

I'd welcome a set of patches into Py3k?only if?the performance for a single-threaded program (and for a multi-threaded but I/O-bound program)?does not decrease”(這個(gè)意思是如果移除GIL鎖,那么單線程性能會(huì)下降,也就是I/O異步性能會(huì)下降)

?

Each Python process gets its own Python interpreter and memory space so the GIL won't be a problem. (每個(gè)進(jìn)程都有一個(gè)GIL鎖)

網(wǎng)上說(shuō)的"Python的多線程是雞肋"的意思指的是多核多線程

有了多線程執(zhí)行異步為啥還要多協(xié)程執(zhí)行IO異步?

根據(jù)[5]:

好處是協(xié)程的開(kāi)銷成本更低.

?

GIL鎖影響的是IO密集還是CPU密集任務(wù)?

The GIL does not have much impact on the performance of I/O-bound multi-threaded programs as the lock is shared between threads while they are waiting for I/O.[4](影響的是CPU密集任務(wù)而不是IO密集任務(wù))

?

GIL鎖在你調(diào)用開(kāi)源庫(kù)的時(shí)候,依然存在嗎?

取決于底層是不是C寫(xiě)的,如果是C寫(xiě)的,屏蔽了GIL鎖,那就不存在,否則就存在

----------------------------------------------------------------------------------------------------------------------

網(wǎng)上關(guān)于屏蔽GIL鎖的資料如下:

[1]屏蔽了GIL鎖,沒(méi)有完整代碼

[3]講了原理,但是沒(méi)有實(shí)操

本篇博客重點(diǎn)解析[2].

GIL鎖每個(gè)進(jìn)程都有一個(gè),鎖的到底是什么?

鎖的是多線程進(jìn)行CPU密集計(jì)算時(shí)候的場(chǎng)景.案例如下[4]:

單線程:

# single_threaded.py import timeCOUNT = 50000000def countdown(n):while n>0:n -= 1start = time.time() countdown(COUNT) end = time.time()print('Time taken in seconds -', end - start)

Time taken in seconds - 2.2484254837036133


多線程:

# multi_threaded.py import time from threading import ThreadCOUNT = 50000000def countdown(n):while n>0:n -= 1t1 = Thread(target=countdown, args=(COUNT//2,)) t2 = Thread(target=countdown, args=(COUNT//2,))start = time.time() t1.start() t2.start() t1.join() t2.join() end = time.time()print('Time taken in seconds -', end - start)

Time taken in seconds - 3.074549674987793

?

多進(jìn)程:

from multiprocessing import Pool import timeCOUNT = 50000000 def countdown(n):while n>0:n -= 1if __name__ == '__main__':pool = Pool(processes=2)start = time.time()r1 = pool.apply_async(countdown, [COUNT//2])r2 = pool.apply_async(countdown, [COUNT//2])pool.close()pool.join()end = time.time()print('Time taken in seconds -', end - start)

結(jié)論:

CPU密集任務(wù)速度上,

多核多進(jìn)程>多核多線程>單線程

----------------------------------------------下面是屏蔽GIL鎖實(shí)踐------------------------------------------------------------------------------

回到前面一個(gè)話題,python的多線程真的是雞肋嗎?

并不是,請(qǐng)看下面實(shí)驗(yàn),下面實(shí)驗(yàn)受到[2]的啟發(fā),但是因?yàn)閇2]的代碼不完整,所以我自己想出了一個(gè)demo

我們把count提升100倍,下面是三個(gè)代碼文件:

pycall.c

#include <stdio.h> #include <stdlib.h> // #include <iostream.h> int foo(int a, int b) { long long int count=5000000000;while( count > 0 ){// cout << "a 的值:" << a << endl;count--;if(count==2500000000)printf("計(jì)數(shù)中%lld\n", count);if(count==0)printf("計(jì)數(shù)結(jié)束%lld\n", count);};printf("you input %d and %d\n", a, b); return 1; }

因?yàn)槲覀兊认乱M(jìn)行多線程測(cè)試,

所以我們?cè)谏厦娲a中故意加入一些if語(yǔ)句用來(lái)監(jiān)控計(jì)數(shù)過(guò)程,如果多線程生效 那么就會(huì)打印兩次,

如果GIL鎖依然存在,那么整個(gè)運(yùn)行過(guò)程會(huì)比單線程還要慢一倍左右

?

pycall-1thread.py

import ctypes import threading import timeif __name__ == '__main__':start=time.time()my_lib=ctypes.cdll.LoadLibrary("./libpycall.so") t1=threading.Thread(target=my_lib.foo,args=(1,1))t1.start()t1.join()end=time.time()print('耗時(shí)=',end-start)

?

pycall-2thread.py

import ctypes import threading import timeif __name__ == '__main__':start=time.time()my_lib=ctypes.cdll.LoadLibrary("./libpycall.so") t1=threading.Thread(target=my_lib.foo,args=(1,1))t2=threading.Thread(target=my_lib.foo,args=(2,2))t1.start()t2.start()t1.join()t2.join()end=time.time()print('耗時(shí)=',end-start)

?

運(yùn)行方法:

先生成.so文件

gcc -o libpycall.so -shared -fPIC pycall.c

然后:

命令運(yùn)行結(jié)果
python pycall-1thread.py計(jì)數(shù)中2500000000
計(jì)數(shù)結(jié)束0
you input 1 and 1
耗時(shí)= 10.828569173812866
python pycall-2thread.py計(jì)數(shù)中2500000000
計(jì)數(shù)中2500000000
計(jì)數(shù)結(jié)束0
you input 1 and 1
計(jì)數(shù)結(jié)束0
you input 2 and 2
耗時(shí)= 10.749252796173096

可以看到,雙線程運(yùn)行與單線程運(yùn)行速度一致,真正發(fā)揮了多核的威力.

所以明白如何使用python的多線程嗎?

在關(guān)鍵部位使用C/C++代碼來(lái)撰寫(xiě),屏蔽GIL鎖,大大提升計(jì)算速度.

C/C++寫(xiě)起來(lái)如果覺(jué)得繁瑣,可以參考o(jì)pencv,很多可以直接拿來(lái)用喔

?

?

Reference:
[1]Python解決GIL鎖的辦法
[2]python的GIL鎖優(yōu)化方案及性能對(duì)比
[3]GIL鎖

[4]What is the Python Global Interpreter Lock (GIL)?

[5]線程和進(jìn)程的區(qū)別是什么? - 無(wú)與童比的回答 - 知乎

[6]python中去掉gil會(huì)大幅降低單線程的執(zhí)行速度,怎么理解?

[7]為什么有人說(shuō) Python 的多線程是雞肋呢? - DarrenChan陳馳的回答 - 知乎

[8]Python 的GIL與線程鎖

[9]Python 中的 GIL 如果可以去掉的話,是不是只要有線程鎖就完全不會(huì)產(chǎn)生負(fù)面影響?

[10]對(duì)于多線程程序,單核cpu與多核cpu是怎么工作的

[11]單核多線程與多核多線程的區(qū)別---總結(jié)

[12]【什么時(shí)候用多線程——CPU篇】

[13]協(xié)程池

[14]多線程有什么用?

[15]How does a single CPU handle Multi-threaded and multi-process applications?

總結(jié)

以上是生活随笔為你收集整理的Cython屏蔽GIL锁实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。