1. 程式人生 > >[Python]IO密集型任務 VS 計算密集型任務

[Python]IO密集型任務 VS 計算密集型任務

IO密集型任務 VS 計算密集型任務

  • 所謂IO密集型任務,是指磁碟IO、網路IO佔主要的任務,計算量很小。比如請求網頁、讀寫檔案等。當然我們在Python中可以利用sleep達到IO密集型任務的目的。
  • 所謂計算密集型任務,是指CPU計算佔主要的任務,CPU一直處於滿負荷狀態。比如在一個很大的列表中查詢元素(當然這不合理),複雜的加減乘除等。


多執行緒 VS 多程序

Python中比較常見的併發方式主要有兩種:多執行緒和多程序。當然還有協程,這裡不做介紹。

1、多執行緒

多執行緒即在一個程序中啟動多個執行緒執行任務。一般來說使用多執行緒可以達到並行的目的,但由於Python中使用了全域性解釋鎖GIL的概念,導致Python中的多執行緒並不是並行執行,而是“交替執行”。類似於下圖:(圖片轉自網路,侵刪)

所以Python中的多執行緒適合IO密集型任務,而不適合計算密集型任務。

Python提供兩組多執行緒介面,一是thread模組_thread,提供低等級介面。二是threading模組,提供更容易使用的基於物件的介面,可以繼承Thread物件來實現執行緒,此外其還提供了其它執行緒相關的物件,例如Timer,Lock等。

2、多程序

由於Python中GIL的原因,對於計算密集型任務,Python下比較好的並行方式是使用多程序,這樣可以非常有效的使用CPU資源。當然同一時間執行的程序數量取決你電腦的CPU核心數。

Python中的程序模組為mutliprocess模組,提供了很多容易使用的基於物件的介面。另外它提供了封裝好的管道和佇列,可以方便的在程序間傳遞訊息。Python還提供了程序池Pool物件,可以方便的管理和控制執行緒。


例項講解Python中的多執行緒、多程序如何應對IO密集型任務、計算密集型任務

本文不會講解Python多執行緒模組、多程序模組的具體用法,想了解的可以參考官方文件。這裡通過一個例項,說明多執行緒適合IO密集型任務,多程序適合計算密集型任務。

首先定義一個佇列,並定義初始化佇列的函式:

# 定義全域性變數Queue
g_queue = multiprocessing.Queue()

def init_queue():
    print("init g_queue start")
    while not g_queue.empty():
        g_queue
.get() for _index in range(10): g_queue.put(_index) print("init g_queue end") return

然後定義IO密集型任務和計算密集型任務,分別從佇列中獲取任務資料:

# 定義一個IO密集型任務:利用time.sleep()
def task_io(task_id):
    print("IOTask[%s] start" % task_id)
    while not g_queue.empty():
        time.sleep(1)
        try:
            data = g_queue.get(block=True, timeout=1)
            print("IOTask[%s] get data: %s" % (task_id, data))
        except Exception as excep:
            print("IOTask[%s] error: %s" % (task_id, str(excep)))
    print("IOTask[%s] end" % task_id)
    return

g_search_list = list(range(10000))
# 定義一個計算密集型任務:利用一些複雜加減乘除、列表查詢等
def task_cpu(task_id):
    print("CPUTask[%s] start" % task_id)
    while not g_queue.empty():
        count = 0
        for i in range(10000):
            count += pow(3*2, 3*2) if i in g_search_list else 0
        try:
            data = g_queue.get(block=True, timeout=1)
            print("CPUTask[%s] get data: %s" % (task_id, data))
        except Exception as excep:
            print("CPUTask[%s] error: %s" % (task_id, str(excep)))
    print("CPUTask[%s] end" % task_id)
    return task_id

準備完上述程式碼之後,進行試驗:

if __name__ == '__main__':
    print("cpu count:", multiprocessing.cpu_count(), "\n")

    print("========== 直接執行IO密集型任務 ==========")
    init_queue()
    time_0 = time.time()
    task_io(0)
    print("結束:", time.time() - time_0, "\n")

    print("========== 多執行緒執行IO密集型任務 ==========")
    init_queue()
    time_0 = time.time()
    thread_list = [threading.Thread(target=task_io, args=(i,)) for i in range(5)]
    for t in thread_list:
        t.start()
    for t in thread_list:
        if t.is_alive():
            t.join()
    print("結束:", time.time() - time_0, "\n")

    print("========== 多程序執行IO密集型任務 ==========")
    init_queue()
    time_0 = time.time()
    process_list = [multiprocessing.Process(target=task_io, args=(i,)) for i in range(multiprocessing.cpu_count())]
    for p in process_list:
        p.start()
    for p in process_list:
        if p.is_alive():
            p.join()
    print("結束:", time.time() - time_0, "\n")

    print("========== 直接執行CPU密集型任務 ==========")
    init_queue()
    time_0 = time.time()
    task_cpu(0)
    print("結束:", time.time() - time_0, "\n")

    print("========== 多執行緒執行CPU密集型任務 ==========")
    init_queue()
    time_0 = time.time()
    thread_list = [threading.Thread(target=task_cpu, args=(i,)) for i in range(5)]
    for t in thread_list:
        t.start()
    for t in thread_list:
        if t.is_alive():
            t.join()
    print("結束:", time.time() - time_0, "\n")

    print("========== 多程序執行cpu密集型任務 ==========")
    init_queue()
    time_0 = time.time()
    process_list = [multiprocessing.Process(target=task_cpu, args=(i,)) for i in range(multiprocessing.cpu_count())]
    for p in process_list:
        p.start()
    for p in process_list:
        if p.is_alive():
            p.join()
    print("結束:", time.time() - time_0, "\n")

結果說明:

對於IO密集型任務:

  • 直接執行用時:10.0333秒
  • 多執行緒執行用時:4.0156秒
  • 多程序執行用時:5.0182秒

說明多執行緒適合IO密集型任務。

對於計算密集型任務

  • 直接執行用時:10.0273秒
  • 多執行緒執行用時:13.247秒
  • 多程序執行用時:6.8377秒

    說明多程序適合計算密集型任務

    =============================================================

    歡迎大家拍磚、提意見。相互交流,共同進步!

    ==============================================================

  • 相關推薦

    [Python]IO密集型任務 VS 計算密集型任務

    IO密集型任務 VS 計算密集型任務 所謂IO密集型任務,是指磁碟IO、網路IO佔主要的任務,計算量很小。比如請求網頁、讀寫檔案等。當然我們在Python中可以利用sleep達到IO密集型任務的目的。 所謂計算密集型任務,是指CPU計算佔主要的任務,CPU一直處於滿負荷狀態。比如在一個很大的列

    Python進階之CPU計算密集型IO密集型

    在最近往伺服器部署爬蟲程式的時候,遇到了一個很奇怪的問題,就是部署上之後執行一段時間或者是直接不執行就進入休眠狀態了,開始一直懷疑是由於伺服器記憶體不足導致的程式休眠,後來廢了好大的勁,最終找到了罪魁禍首,具體分析我通過這幾篇連載的部落格來分析一下,正好也對給自己充充電。 第一種任務的型別是

    python計算密集型任務多程序最佳使用的核數

    import time from multiprocessing import Pool from tqdm import tqdm import pandas as pd import matplotlib.pyplot as plt def run(i): cou

    Python筆記-計算密集型(最好用C)、IO密集型(最好用指令碼)

    計算密集型 1、特點:要進行大量的計算,消耗CPU資源。比如計算圓周率、對視訊進行高清解碼等等,全靠CPU的運算能力。 2、計算密集型任務雖然也可以用多工完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,所以,要最高效地利用CPU,計

    計算密集型IO密集型、資料密集型

    計算密集型(CPU-Intensive) 1、特點:要進行大量的計算,消耗CPU資源。比如計算圓周率、對視訊進行高清解碼等等,全靠CPU的運算能力。 2、計算密集型任務雖然也可以用多工完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,所以,要最高效地利用CPU,計算密

    IO密集型計算密集型、執行緒和程序

    io密集型:有阻塞的狀態,就是一直會執行CPU(中間就一個等待狀態,這個就叫做IO密集型)。例如:sleep狀態 計算密集型任務:沒有等待的狀態就是計算密集型,從上到下執行沒有等待。 在Python中沒法同時使用多個CPU,在同一時刻,多個執行緒是互相搶佔資源的,在cpython執行中加了一把鎖(GIL)

    CPU io-密集型 計算密集型

    核心是可以分別獨立執行程式指令的計算單元。 執行緒是作業系統能夠進行運算排程的最小單位。 有一個原則是:活躍執行緒數為 CPU(核)數時最佳。過少的活躍執行緒導致 CPU 無法被充分利用,過多的活躍執行緒導致過大的執行緒上下文切換開銷。 執行緒應該是活躍的,處於 IO 的

    計算密集型&IO密集型

    原文:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001397567993007df355a3394da48f0bf14960f0c78753f000

    執行緒與程序 計算密集型 IO密集型

    執行緒與程序:   執行緒和程序通常都有一個主線/程序的負責分配任務和其他子線/程序負責執行任何。   多程序的優點在於一個子程序掛了,不會影響其他程序(主程序掛了就全掛了),但是其建立的代價較大,Apache採用的就是多程序機制;   而多執行緒一般要比

    計算密集型IO密集型

    計算密集型 計算密集型任務的特點是要進行大量的計算,消耗CPU資源,比如計算圓周率、對視訊進行高清解碼等等,全靠CPU的運算能力。這種計算密集型任務雖然也可以用多工完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,所以,要最高效地利用CPU,計算密集

    Python學習筆記 - day14 - Celery異步任務

    mage 名稱 完成 異步消息 安裝 裝飾器 可能 一段 god Celery概述 關於celery的定義,首先來看官方網站: Celery(芹菜) 是一個簡單、靈活且可靠的,處理大量消息的分布式系統,並且提供維護這樣一個系統的必需工具。 簡單來看,是一個基於pytho

    python通過多進程實行多任務

    -s hung name 哪裏 簡單 共享 不相信 time 多任務 #原創,轉載請聯系 在開始之前,我們要知道什麽是進程。道理很簡單,你平時電腦打開QQ客戶端,就是一個進程。再打開一個QQ客戶端,又是一個進程。那麽,在python中如何用一篇代碼就可以開

    python中的APScheduler模組(定時任務1)

    在平常的工作中幾乎有一半的功能模組都需要定時任務來推動,例如專案中有一個定時統計程式,定時爬出網站的URL程式,定時檢測釣魚網站的程式等等,都涉及到了關於定時任務的問題,第一時間想到的是利用time模組的time.sleep()方法使程式休眠來達到定時任務的目的,雖然這樣也可以,但是總覺得不是那麼的

    python協程之動態添加任務

    獲取 detail dsa 不能 clas python 使用 rt thread get https://blog.csdn.net/qq_29349715/article/details/79730786 python協程只能運行在事件循環中,但是一旦事件循環運行,

    為什麼PHP不適合計算密集型業務

    回答這個問題,我們來了解一下為什麼說PHP慢? PHP的慢是相對於C/C++級別的語言來說,事實上,PHP語言最初的設計,就不是用來解決計算密集型的應用場景。我們可以這樣粗略理解為,PHP為了提升開發效率,而犧牲了執行效率。 我們知道PHP一個很大的特點,就是弱型別特性,也就是說,我可以隨意定義一個變數,然

    CPU-bound(計算密集型) 和 I/O bound(I/O密集型)

    如果所有的任務都是計算(CPU)密集型的,則建立處理器可用核心數這麼多個執行緒就可以了,這樣已經充分利用了處理器,也就是讓它以最大火力不停進行計算。建立更多的執行緒對於程式效能反而是不利的,因為多個執行緒間頻繁進行上下文切換對於程式效能損耗較大。執行緒數=cpu核心數+1

    將複雜的大任務拆分成多個簡單的小任務進行計算

    package thread; import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Fut

    VS code 提示“任務僅可在工作區資料夾上可用”

    /*本人新手小白一枚,在使用VS code時,執行任務,提示“任務僅可在工作區資料夾上可用”,不知道這是啥問題,百度了半天也沒解決辦法,後來在知乎找到了方法,特此記錄下來,如果有小小白遇到此問題,可以參考。*/ ------------------ 原因:沒開啟工作區(就

    現已推出 – Amazon EC2 的計算密集型 C5 例項

    我很高興地宣佈,新的計算密集型 C5 例項今天在三個 AWS 區域推出,有六種大小規格! 這些例項專用於計算密集型應用程式,例如批處理、分散式分析、高效能運算 (HPC)、廣告服務、高度可擴充套件的多人遊戲和視訊編碼。新例項提供了比 C4 例項高 25% 的價格/效能改進,對

    並行流計算--統計1-n的和,計算密集型

    import java.util.function.Function; import java.util.stream.LongStream; import java.util.stream.Stream; public class ParalleStreamDemo {