為Python正名:語言本身不是瓶頸,可能是外部資源出了問題
Python 真的很慢嗎?這需要具體問題具體分析。和 C 等編譯型語言相比,Python 在處理數(shù)字方面速度確實很慢。這也從側面說明了 Python 中加速數(shù)字處理的庫(如 numpy)為什么如此重要了。
但是,Python 是不是在所有用例上都比其他編程語言慢呢?并非如此,如果了解一下為解決特定問題而優(yōu)化的許多 Python 庫的性能基準測試,你就會發(fā)現(xiàn) Python 比編譯型語言做得好。以 FastAPI 性能基準為例,F(xiàn)astAPI 是一個用于構建 API 的現(xiàn)代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于標準的 Python 類型提示。Go 語言顯然比 Python 快,不過,F(xiàn)astAPI 在構建 REST API 方面勝過了 Go 的一些庫:
Web 框架基準測試,不包括 C++ 和 Java web 框架。
同樣,在比較 Dask(使用 Python 編寫)與 Spark(使用 Scala 編寫)處理數(shù)據(jù)密集型神經(jīng)成像 pipeline 時,結果表明這兩個引擎之間沒有實質的性能差異。
代碼速度 VS 實用性
從實用的角度來看,在為日常工作選擇編程語言時,需要回答多個不同的問題。
(1) 問題 1:這種語言能夠可靠地解決多項業(yè)務問題嗎?
如果你只關心速度,那么不要用 Python,各種用例都有更快的替代方案。Python 的主要優(yōu)點在于可讀性、易用性和可解決大量問題。Python 可以作為粘合劑,將不同的系統(tǒng)、服務和用例連接在一起。
(2) 問題 2:你能找到足夠多懂這門語言的員工嗎?
Python 易于學習和使用,因此用戶數(shù)量不斷增長。以前使用 Excel 處理數(shù)字業(yè)務的用戶,現(xiàn)在可以很快學會用 Pandas 編寫代碼,從而學會在不依賴 IT 資源的情況下實現(xiàn)自給自足。同時,這也緩解了 IT 和分析部門的負擔。
如今,企業(yè)更容易找到會 Python、并能用這種語言維護 Spark 數(shù)據(jù)處理應用程序的數(shù)據(jù)工程師,而不是用 Java 或 Scala 做同樣工作的人。許多組織在很多用例中逐漸轉向使用 Python,因為懂 Python 的員工更容易找到。
相比之下,一些公司迫切需要 Java 或 C# 開發(fā)人員來維護他們現(xiàn)有的應用程序,但這些語言很難(需要數(shù)年才能掌握),而且對于新手程序員來說似乎沒有吸引力,他們可能使用更簡單的語言(如 Go 或 Python)在工作中掙到更多的錢。
(3) 問題 3:不同領域專家之間的協(xié)同效應
如果你的公司使用 Python,那么業(yè)務用戶、數(shù)據(jù)分析師、數(shù)據(jù)科學家、數(shù)據(jù)工程師、后端和 web 開發(fā)人員、運維工程師甚至系統(tǒng)管理員很可能使用同一種語言。這將在項目中產(chǎn)生協(xié)同效應,來自不同領域的人可以一起工作并利用相同的工具。
數(shù)據(jù)處理的真正瓶頸是什么?
在平時的工作中,通常我們遇到的瓶頸不是語言本身,而是外部資源。讓我們看幾個例子。
(1) 示例 1:寫入關系型數(shù)據(jù)庫
當以 ETL 方式處理數(shù)據(jù)時,最終我們需要將這些數(shù)據(jù)加載到某個集中的地方。雖然我們可以利用 Python 中的多線程,更快地將數(shù)據(jù)寫入某些關系型數(shù)據(jù)庫,但并行寫入次數(shù)的增加可能會使該數(shù)據(jù)庫的 CPU 容量達到極限。
這意味著 Python 具備并行化和加速操作的機制,但是關系型數(shù)據(jù)庫(受 CPU 核數(shù)的限制)有其局限性,僅通過更快的編程語言很難解決。
(2) 示例 2:調用外部 API
另一個例子是使用外部 REST API,以提取數(shù)據(jù)來滿足數(shù)據(jù)分析需求,這一案例中語言本身似乎并不是瓶頸。雖然我們可以利用并行加速來提取數(shù)據(jù),但這可能是徒勞的,因為許多外部 API 限制了在特定時間段內(nèi)發(fā)出請求的數(shù)量。因此,我們會故意讓腳本變慢,以確保不會超過 API 的請求限制:
- time.sleep(10)
(3) 示例 3:處理大數(shù)據(jù)
從處理超大數(shù)據(jù)集的經(jīng)驗來說,無論用什么語言你都不能直接用筆記本內(nèi)存來負載大數(shù)據(jù)。這種情況下,你需要利用 Dask、Spark、Ray 等分布式處理框架。在使用單個服務器實例或者筆記本時,處理的數(shù)據(jù)量存在限制。
如果你想把實際的數(shù)據(jù)處理工作轉移到一個計算節(jié)點集群中,甚至使用 GPU 來加速計算,Python 恰好有一個龐大的框架生態(tài)系統(tǒng),使這個任務變得更容易:
- 你是否想用 GPU 來加快數(shù)據(jù)科學的計算速度?使用 PyTorch、TensorFlow、Ray 或 Rapids(甚至 SQL - BlazingSQL)。
- 你是否想加速 Python 代碼處理大數(shù)據(jù)的速度?使用 Spark(或 Databricks)、Dask 或 Prefect。
- 你是否想加快數(shù)據(jù)分析的處理速度?使用快速的專用內(nèi)存列數(shù)據(jù)庫,通過使用 SQL 查詢確保高速處理。
此外,如果你需要協(xié)調、監(jiān)測計算節(jié)點集群上發(fā)生的數(shù)據(jù)處理,你有 Apache Airflow、Prefect 或 Dagster 等多個 Python 工作流管理平臺可供選擇,它們可以加速數(shù)據(jù) pipeline 的開發(fā)和維護。
順帶提一下,一些人可能會抱怨 Python 沒有充分利用其能力或者未對手頭問題使用合適的數(shù)據(jù)結構。
總而言之,如果你需要快速處理大量數(shù)據(jù),那你更需要的是計算資源而不是快速的編程語言,而且一些 Python 庫能夠輕松實現(xiàn)在數(shù)百個節(jié)點上的分布式工作。
原文鏈接:https://towardsdatascience.com/is-python-really-a-bottleneck-786d063e2921
【本文是51CTO專欄機構“機器之心”的原創(chuàng)譯文,微信公眾號“機器之心( id: almosthuman2014)”】