Python中的並行處理
介紹
在當今快節奏的數字環境中,有效完成計算密集型任務對於開發人員和資料科學家至關重要。幸運的是,Python 憑藉其適應性和廣泛的生態系統,提供了強大的並行處理能力。透過將複雜問題分解成更小、更易於管理的任務,這些任務可以併發執行,我們可以獲得巨大的效能提升。
Python 的並行處理功能使我們能夠透過利用可用的計算資源,更快速、更有效地處理諸如網路抓取、科學模擬和資料分析等任務。在這篇文章中,我們將踏上 Python 並行處理之旅。我們將探索多種方法,包括多程序、非同步程式設計和多執行緒,並學習如何有效地利用它們來克服系統中的效能瓶頸。加入我們,一起釋放 Python 並行處理的全部潛能,並達到效能和生產力的新高度。
瞭解並行處理
並行處理是指將一項任務分解成較小的子任務,並在多個處理器或核心上併發執行這些子任務。透過有效利用可用的計算資源,並行處理可以顯著減少程式的總執行時間。Python 提供了多種並行處理方法,包括非同步程式設計、多程序和多執行緒。
Python 中的多執行緒
多執行緒方法利用單個程序內的多個執行緒併發執行,同時共享相同的記憶體。Python 的 threading 模組可以輕鬆實現多執行緒。然而,由於全域性直譯器鎖 (GIL),Python 中的多執行緒對於 CPU 密集型操作可能不會帶來明顯的加速,因為 GIL 每次只允許一個執行緒執行 Python 位元組碼。但是,多執行緒對於 I/O 密集型任務很有用,因為它允許執行緒在等待 I/O 操作完成時執行其他操作。
讓我們來看一個使用多執行緒下載多個網頁的示例
示例
import threading import requests
def download_page(url):
response = requests.get(url)
print(f"Downloaded {url}")
urls = [
"https://example.com",
"https://google.com",
"https://openai.com"
]
threads = []
for url in
urls:
thread = threading.Thread(target=download_page,
args=(url,)) thread.start() threads.append(thread)
for thread in threads:
thread.join()
輸出
Downloaded https://example.com Downloaded https://google.com Downloaded https://openai.com
上面的程式碼片段透過在自己的執行緒中下載每個 URL,實現了多個下載的併發執行。join() 函式確保主執行緒在每個執行緒完成之前等待。
Python 中的多程序
與多執行緒不同,多程序透過使用多個程序(每個程序都有自己的記憶體空間)來提供真正的並行性。Python 的 multiprocessing 模組提供了一個用於實現多程序的高階介面。多程序適用於 CPU 密集型任務,因為每個程序都在一個單獨的 Python 直譯器中執行,從而避免了 GIL 對多執行緒的限制。
下面的程式碼使用了多程序。一旦 pool 類建立了一個工作程序池,map() 方法就會將任務分配到可用的程序中。results 列表是結果的集合。
考慮下面的示例,我們使用多程序對列表中的每個整數進行平方運算
示例
import multiprocessing
def square(number):
return number ** 2
numbers = [1, 2, 3, 4, 5]
with multiprocessing.Pool() as pool:
results = pool.map(square, numbers)
print(results)
輸出
[1, 4, 9, 16, 25]
Python 中的非同步程式設計
透過利用非阻塞操作,非同步程式設計可以有效地執行 I/O 密集型任務。藉助 asyncio 包,可以使用協程、事件迴圈和期貨來建立 Python 中的非同步程式碼。隨著網路應用程式和 API 的日益普及,非同步程式設計變得越來越重要。
下面的程式碼示例中,fetch_page() 協程使用 aiohttp 非同步獲取網頁。main() 方法建立了一個任務列表,然後使用 asyncio.gather() 併發執行這些任務。await 關鍵字用於等待任務完成並獲取結果。
讓我們來看一個使用 asyncio 和 aiohttp 非同步獲取多個網頁的示例
示例
import asyncio
import aiohttp
async def fetch_page(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://example.com",
"https://google.com",
"https://openai.com"
]
tasks = [fetch_page(url) for url in urls] pages = await asyncio.gather(*tasks)
print(pages)
asyncio.run(main())
輸出
['<!doctype html>\n<html>\n<head>\n <title>Example Domain</title>\n\n <meta
charset="utf-8" />\n <meta http-equiv="Content-type"content="text/html; charset=utf-8" />\n <meta name="viewport" content="width=device-width, initialscale=1" />\n <style type="text/css">\n body {\n background-color: #f0f0f2;\n margin: 0;\n padding: 0;\n font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;\n \n }\n div {\n width: 600px;\n margin: 5em auto;\n padding: 50px;\n background-color: #fff;\n border-radius: 1em;\n }\n a:link, a:visited {\n color: #38488f;\n text-decoration: none;\n }\n @media (maxwidth: 700px) {\n body {\n background-color: #fff;\n }\n div {\n width: auto;\n margin: 0 auto;\n border-radius: 0;\n padding: 1em;\n }\n }\n </style> \n</head>\n\n<body>\n<div>\n <h1>Example Domain</h1>\n <p>This domain is for use in illustrative examples in documents. You may use this\n domain in literature without prior coordination or asking for permission.</p>\n <p><a href="https://www.iana.org/domains/example">More information...</a></p>\n</div>\n</body>\n</html>', '<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en"><head><meta content="Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for." name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/logos/doodles/2021/mom-
and-dad-6116550989716480.2-law.gif" itemprop="image"><link href="/logos/doodles/2021/mom-and-dad-6116550989716480.2-law.gif" rel="icon" type="image/gif"><title>Google</title><script nonce="sJwM0Ptp5a/whzxPtTD8Yw==">(function(){window.google={kEI:'cmKgYY37A7 K09QPhzKuACw',kEXPI:'1354557,1354612,1354620,1354954,1355090,1355493,13556
83,3700267,4029815,4031109,4032677,4036527,4038022,4043492,4045841,4048347,4
048490,4052469,4055589,4056520,4057177,4057696,4060329,4060798,4061854,4062 531,4064696,406 '
選擇正確的方法
Python 的並行處理技術根據手頭任務的具體情況而有所不同。以下是一些指導原則,可幫助您做出明智的決策
對於 I/O 密集型任務,其中大部分執行時間都花費在等待輸入/輸出操作上,多執行緒是合適的。它非常適合諸如下載檔案、使用 API 和操作檔案等任務。由於 Python 的全域性直譯器鎖 (GIL),多執行緒可能不會顯著加速 CPU 密集型任務。
另一方面,多程序非常適合涉及密集計算的 CPU 密集型任務。它透過利用多個程序(每個程序都有自己的記憶體空間)來實現真正的並行性,並繞過了 GIL 的限制。但是,它在記憶體消耗和程序間通訊方面會產生額外的開銷。
對於涉及網路操作的 I/O 密集型任務,使用 asyncio 等庫執行的非同步程式設計很有用。它利用非阻塞 I/O 操作,以便任務可以繼續進行,而無需等待每個操作完成。此方法有效地管理多個併發連線,使其適用於網路伺服器開發、Web API 互動和網路抓取。非同步程式設計最大程度地減少了 I/O 操作的等待時間,確保響應能力和可擴充套件性。
結論
Python 的並行處理能力提供了機會來提高需要複雜計算的任務的效率。無論您選擇使用多執行緒、多程序還是非同步程式設計,Python 都提供了必要的工具和模組來有效地利用併發性。透過理解您的任務的性質並選擇合適的方法,您可以最大限度地利用並行處理的優勢並縮短執行時間。因此,請大膽探索,充分利用 Python 的並行性來建立更快、更高效的應用程式。
資料結構
網路
RDBMS
作業系統
Java
iOS
HTML
CSS
Android
Python
C 程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP