亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

Python并發編程(一)

2023-09-08 09:30:30
4
0

在介紹python并發編程前先介紹下并行與并發得概念

并發:指一個處理器同時處理多個任務,例如一共兩個任務,看電視和學習,你在一邊學習一邊看電視,大概是學習一會兒看一會電視的狀態

并行:指多個處理器或者是多核的處理器同時處理多個不同的任務,例如一共兩個任務,玩手機和學習,你負責玩手機,學霸負責學習,這是對任務的并行處理

并發是邏輯上的同時發生(simultaneous),而并行是物理上的同時發生。

上面的例子舉得不好,看起來并發并不能提高任務的效率,其實不是這樣的,具體情況是看電視時碰到了廣告,你去學習,而不是等待廣告結束,這樣時間就被利用起來了,也就是在一個任務遇到了瓶頸先去做另一個任務,而不是原地等待

python并發編程也大概是這個意思,在程序中有線程和進程兩個概念,程序運行的效率也可以多線程和多進程兩個方面去提升

進程:是并發執行的程序在執行過程中分配和管理資源的基本單位,是一個動態概念,競爭計算機系統資源的基本單位。

線程:是進程的一個執行單元,是進程內科調度實體。比進程更小的獨立運行的基本單位。線程也被稱為輕量級進程。

進程與線程的區別:

  • 地址空間:線程共享本進程的地址空間,而進程之間是獨立的地址空間。

  • 資源:線程共享本進程的資源如內存、I/O、cpu等,不利于資源的管理和保護,而進程之間的資源是獨立的,能很好的進行資源管理和保護。

  • 健壯性:多進程要比多線程健壯,一個進程崩潰后,在保護模式下不會對其他進程產生影響,但是一個線程崩潰整個進程都死掉。

  • 執行過程:每個獨立的進程有一個程序運行的入口、順序執行序列和程序入口,執行開銷大。但是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制,執行開銷小。

  • 切換時:進程切換時,消耗的資源大,效率高。所以涉及到頻繁的切換時,使用線程要好于進程。同樣如果要求同時進行并且又要共享某些變量的并發操作,只能用線程不能用進程。

從上面的區別可以搞清楚什么時候要用多線程什么時候用多進程

但python還有一個特性,就是python的GIL鎖,鎖在很多編程語言中都有出現,前面提到了線程會共享本進程的資源,因為在并發編程中會對多個線程會對同一個資源進行操作,這時會出現線程安全問題,鎖就是用來解決這個問題的,類似于數據庫中的臟數據,而python的GIL鎖在任意時刻只允許一個 Python 進程使用 Python 解釋器。也就是任意時刻,Python 只有一個線程在運行。

看到這里很多人會感到疑惑,如果在任意時刻,Python 只有一個線程在運行,那多線程不就沒有什么意義了

其實不是這樣的,準確的說,由于GIL的機制,單核CPU在同一時刻只有一個線程在運行。但當線程遇到IO操作或Timer Tick到期,釋放GIL鎖,那么Time Tick到期是什么呢?Time Tick規定了線程的最長執行時間,超過時間后自動釋放GIL鎖。

所以在某些場景下,python多線程對程序性能還是有很大提升的

程序的瓶頸一般是計算和IO等耗時操作,所以可以把任務分為計算密集型IO密集型

計算密集型:一般是指服務器的硬盤、內存硬件性能相對CPU好很多,或者使用率低很多。系統運行CPU讀寫I/O(硬盤/內存)時可以在很短的時間內完成,幾乎沒有阻塞(等待I/O的實時間)時間,而CPU一直有大量運算要處理,因此CPU負載長期過高。

IO密集型:一般是指服務器CPU的性能相對硬盤、內存硬件好很多,或者使用率低很多。系統運行多是CPU在等I/O (硬盤/內存) 的讀寫操作,此類情景下CPU負載并不高。

總結,由于python的GIL鎖,如果程序是計算密集型,使用多線程是對代碼不會有太大幫助的,而應該使用多進程,如果程序是IO密集型,那么優先使用多線程,因為多進程的資源開銷更大

如下經典示例代碼,此代碼的瓶頸主要在計算而非IO

未使用多線程、多進程

import time
from threading import Thread

COUNT = 50000000

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

start = time.time()
countdown(COUNT)
end = time.time()

print('Time taken in seconds -', end - start)

耗時

Time taken in seconds - 2.205103874206543

使用多線程

import time
from threading import Thread

COUNT = 50000000

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

t1 = 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 - 2.226524829864502

可以看到,性能基本沒有提升,還慢了一點點,考慮到誤差,兩者性能基本一樣

from multiprocessing import Pool
import time

COUNT = 50000000
def countdown(n):
    while n>0:
        n -= 1

if __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)

耗時

 Time taken in seconds - 1.4109129905700684

可以看到多進程對與計算密集型程序性能提升還是非常明顯的,如果你覺得不夠明顯,可以把計算量調大,就是代碼中的COUNT值,效果會更加明顯

0條評論
0 / 1000
張****宇
5文章數
0粉絲數
張****宇
5 文章 | 0 粉絲
原創

Python并發編程(一)

2023-09-08 09:30:30
4
0

在介紹python并發編程前先介紹下并行與并發得概念

并發:指一個處理器同時處理多個任務,例如一共兩個任務,看電視和學習,你在一邊學習一邊看電視,大概是學習一會兒看一會電視的狀態

并行:指多個處理器或者是多核的處理器同時處理多個不同的任務,例如一共兩個任務,玩手機和學習,你負責玩手機,學霸負責學習,這是對任務的并行處理

并發是邏輯上的同時發生(simultaneous),而并行是物理上的同時發生。

上面的例子舉得不好,看起來并發并不能提高任務的效率,其實不是這樣的,具體情況是看電視時碰到了廣告,你去學習,而不是等待廣告結束,這樣時間就被利用起來了,也就是在一個任務遇到了瓶頸先去做另一個任務,而不是原地等待

python并發編程也大概是這個意思,在程序中有線程和進程兩個概念,程序運行的效率也可以多線程和多進程兩個方面去提升

進程:是并發執行的程序在執行過程中分配和管理資源的基本單位,是一個動態概念,競爭計算機系統資源的基本單位。

線程:是進程的一個執行單元,是進程內科調度實體。比進程更小的獨立運行的基本單位。線程也被稱為輕量級進程。

進程與線程的區別:

  • 地址空間:線程共享本進程的地址空間,而進程之間是獨立的地址空間。

  • 資源:線程共享本進程的資源如內存、I/O、cpu等,不利于資源的管理和保護,而進程之間的資源是獨立的,能很好的進行資源管理和保護。

  • 健壯性:多進程要比多線程健壯,一個進程崩潰后,在保護模式下不會對其他進程產生影響,但是一個線程崩潰整個進程都死掉。

  • 執行過程:每個獨立的進程有一個程序運行的入口、順序執行序列和程序入口,執行開銷大。但是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制,執行開銷小。

  • 切換時:進程切換時,消耗的資源大,效率高。所以涉及到頻繁的切換時,使用線程要好于進程。同樣如果要求同時進行并且又要共享某些變量的并發操作,只能用線程不能用進程。

從上面的區別可以搞清楚什么時候要用多線程什么時候用多進程

但python還有一個特性,就是python的GIL鎖,鎖在很多編程語言中都有出現,前面提到了線程會共享本進程的資源,因為在并發編程中會對多個線程會對同一個資源進行操作,這時會出現線程安全問題,鎖就是用來解決這個問題的,類似于數據庫中的臟數據,而python的GIL鎖在任意時刻只允許一個 Python 進程使用 Python 解釋器。也就是任意時刻,Python 只有一個線程在運行。

看到這里很多人會感到疑惑,如果在任意時刻,Python 只有一個線程在運行,那多線程不就沒有什么意義了

其實不是這樣的,準確的說,由于GIL的機制,單核CPU在同一時刻只有一個線程在運行。但當線程遇到IO操作或Timer Tick到期,釋放GIL鎖,那么Time Tick到期是什么呢?Time Tick規定了線程的最長執行時間,超過時間后自動釋放GIL鎖。

所以在某些場景下,python多線程對程序性能還是有很大提升的

程序的瓶頸一般是計算和IO等耗時操作,所以可以把任務分為計算密集型IO密集型

計算密集型:一般是指服務器的硬盤、內存硬件性能相對CPU好很多,或者使用率低很多。系統運行CPU讀寫I/O(硬盤/內存)時可以在很短的時間內完成,幾乎沒有阻塞(等待I/O的實時間)時間,而CPU一直有大量運算要處理,因此CPU負載長期過高。

IO密集型:一般是指服務器CPU的性能相對硬盤、內存硬件好很多,或者使用率低很多。系統運行多是CPU在等I/O (硬盤/內存) 的讀寫操作,此類情景下CPU負載并不高。

總結,由于python的GIL鎖,如果程序是計算密集型,使用多線程是對代碼不會有太大幫助的,而應該使用多進程,如果程序是IO密集型,那么優先使用多線程,因為多進程的資源開銷更大

如下經典示例代碼,此代碼的瓶頸主要在計算而非IO

未使用多線程、多進程

import time
from threading import Thread

COUNT = 50000000

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

start = time.time()
countdown(COUNT)
end = time.time()

print('Time taken in seconds -', end - start)

耗時

Time taken in seconds - 2.205103874206543

使用多線程

import time
from threading import Thread

COUNT = 50000000

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

t1 = 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 - 2.226524829864502

可以看到,性能基本沒有提升,還慢了一點點,考慮到誤差,兩者性能基本一樣

from multiprocessing import Pool
import time

COUNT = 50000000
def countdown(n):
    while n>0:
        n -= 1

if __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)

耗時

 Time taken in seconds - 1.4109129905700684

可以看到多進程對與計算密集型程序性能提升還是非常明顯的,如果你覺得不夠明顯,可以把計算量調大,就是代碼中的COUNT值,效果會更加明顯

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0