天天看點

Python多程序和多線程的使用場景Python多程序适用的場景:計算密集型(CPU密集型)任務Python多線程适用的場景:IO密集型任務

Python多程序适用的場景:計算密集型(CPU密集型)任務

Python多線程适用的場景:IO密集型任務

計算密集型任務一般指需要做大量的邏輯運算,比如上億次的加減乘除,使用多核CPU可以并發提高計算性能。

IO密集型任務一般指輸入輸出型,比如檔案的讀取,或者網絡的請求,這類場景一般會遇到IO阻塞,使用多核CPU來執行并不會有太高的性能提升。

下面使用一台64核的虛拟機來執行任務,通過示例代碼來差別它們,

示例1:執行計算密集型任務,進行1億次運算

使用多程序

from multiprocessing import Process
import os, time


# 計算密集型任務
def work():
    res = 0
    for i in range(100 * 100 * 100 * 100):  # 億次運算
        res *= i


if __name__ == "__main__":
    l = []
    print("本機為", os.cpu_count(), "核 CPU")  # 本機為64核
    start = time.time()
    for i in range(4):
        p = Process(target=work)  # 多程序
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print("計算密集型任務,多程序耗時 %s" % (stop - start))
           

使用多線程

from threading import Thread
import os, time


# 計算密集型任務
def work():
    res = 0
    for i in range(100 * 100 * 100 * 100):  # 億次運算
        res *= i


if __name__ == "__main__":
    l = []
    print("本機為", os.cpu_count(), "核 CPU")  # 本機為64核
    start = time.time()
    for i in range(4):
        p = Thread(target=work)  # 多線程
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print("計算密集型任務,多線程耗時 %s" % (stop - start))
           

兩段代碼輸出:

本機為 64 核 CPU
計算密集型任務,多程序耗時 6.864224672317505

本機為 64 核 CPU
計算密集型任務,多線程耗時 37.91042113304138
           

說明:上述代碼中,分别使用4個多程序和4個多線程去執行億次運算,多程序耗時6.86s,多線程耗時37.91s,可見在計算密集型任務場景,使用多程序能大大提高效率。

另外,當分别使用8個多程序和8個多線程去執行億次運算時,耗時差距更大,輸出如下:

本機為 64 核 CPU
計算密集型任務,多程序耗時 6.811635971069336

本機為 64 核 CPU
計算密集型任務,多線程耗時 113.53767895698547
           

可見在64核的cpu機器下,同時使用8個多程序和4個多程序效率幾乎一樣。而使用多線程則就效率較慢。要最高效地利用CPU,計算密集型任務同時進行的數量應當等于CPU的核心數

示例2:400次,阻塞兩秒,讀取檔案

使用多程序(4核cpu)

from multiprocessing import Process
import os, time


# I/0密集型任務
def work():
    time.sleep(5)  # 阻塞兩秒


if __name__ == "__main__":
    l = []
    print("本機為", os.cpu_count(), "核 CPU")
    start = time.time()
    for i in range(1000):
        p = Process(target=work)  # 多程序
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print("I/0密集型任務,多程序耗時 %s" % (stop - start))
           

使用多線程(4核cpu)

from threading import Thread
import os, time


# I/0密集型任務
def work():
    time.sleep(5)  # 阻塞兩秒


if __name__ == "__main__":
    l = []
    print("本機為", os.cpu_count(), "核 CPU")
    start = time.time()

    for i in range(1000):
        p = Thread(target=work)  # 多線程
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop = time.time()
    print("I/0密集型任務,多線程耗時 %s" % (stop - start))
           

輸出:

本機為 64 核 CPU
I/0密集型任務,多程序耗時 12.28218412399292


本機為 64 核 CPU
I/0密集型任務,多線程耗時 5.399136066436768
           

說明:python的多線程有于GIL鎖的存在,無論是多少核的cpu機器,也隻能使用單核,從輸出結果來看,對于IO密集型任務使用多線程比較占優。

FAQ:執行多程序的io密集型任務時,報了一個錯:

OSError: [Errno 24] Too many open files

原因:linux系統限制

ulimit -n
#  輸出 1024
           

解決:(臨時提高系統限制,重新開機後失效)

ulimit -n 10240