簡體   English   中英

有沒有辦法利用 asyncio 的多個 CPU 內核?

[英]Is there a way to take advantage of multiple CPU cores with asyncio?

我用 python 和 asyncio 創建了一個簡單的 HTTP 服務器。 但是,我讀到基於異步的服務器只能利用一個 CPU 內核。 我正在嘗試通過multiprocessing來解決這個問題,但它不起作用。 當我嘗試創建一個進程時,它給了我一個錯誤,說它不能從 _winapi 創建進程。 到目前為止,這是我的代碼:

def serve_forever(self, host, port):
    srv, loop = self.init(host, port)
    print()
    if self.name:
        print('* Serving App {}'.format(self.name))
    print('* Serving On http://{host}:{port}'.format(host=host, port=port))
    print('* Press <CTRL-C> To Quit')
    workers = []
    try:
        for i in range(mp.cpu_count()-1):
            p = mp.Process(target=loop.run_forever)
            workers.append(p)
            p.start()
        loop.run_forever()
    except KeyboardInterrupt:
        print()
        for p in workers:
            p.terminate()
        srv.close()
        loop.run_until_complete(srv.wait_closed())
        loop.close()
        pass

順便說一句, self.init function 有效。

我認為,您可能在並行編程和並發編程之間有些混淆。 乍一看,它們可能看起來很相似,但您很快就會意識到它們非常不同。

Asyncio 有助於並發,這意味着您可以以非阻塞方式編寫代碼。 換句話說,對於需要時間來響應的 I/O 操作,例如網絡調用或磁盤訪問,您可以讓一段特定的代碼在等待響應時不會阻塞您的進程。 這為同一線程中代碼的其他異步部分釋放了 CPU 周期。

並行編程涉及將某些更高級別任務的一小部分委托給多個進程或線程,並且(通常)在所有完成后收集和合並結果。

以下是幫助區分的三種方案:

您可以編寫一個服務器程序,以便接收到的每個請求都由一個新線程處理。 該線程可能 100% 阻塞,因此如果它進行網絡調用或從磁盤讀取文件,它將等待 I/O 任務完成。 但這沒關系,因為它在自己的線程中,操作系統將負責切換哪些線程何時運行,在哪些內核上運行等,因此其他線程將有機會在該線程等待 I/O 時運行. 這樣做的缺點是線程有資源開銷,並且操作系統對線程中發生的事情沒有完全了解,它只是盡其所能確保它們都得到公平的轉折。

服務器的另一個版本可以以並發方式編寫。 這里只使用了一個線程,但該線程對阻塞和執行的內容有詳細的了解(asyncio to the rescue),所以你可以編寫一次只處理一個請求的代碼,但是當給定的請求正在等待時數據它允許另一個請求進行一些處理,在任務之間切換而其他任務被阻塞,所有這些都在同一個線程/進程中。 這是一種更有效的資源使用方式,但它通常只適合高 I/O 工作負載,例如讀取/寫入數據庫的簡單服務器。 對於必須為每個請求進行大量大型計算的服務器來說,這並不是很好,因為在計算過程中不會有 I/O 事件來觸發任務切換。

第三種情況是您將這兩個概念結合起來。 這有助於擴展處理大量 I/O 操作的異步服務器。 它也可以用於需要處理大量連接和長時間運行的任務,其中任務被委派給線程或其他更復雜的配置,但實際上它對於擴展最有用。

Asyncio 有一些對子進程的內置支持

我強烈推薦閱讀這篇文章,它非常好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM