-
1 # 你看我獨角獸嗎
-
2 # 心境讀書
從語言的本質上來講,python是解釋型語言,而c++是編譯型語言。
也就是說python程式碼解釋一句,執行一句;而c++語言是講整個程式碼編譯、連結為機器可識別的二進位制程式碼,最後一起執行。
所以從這個角度來講,c++自然會比python在很多情況下快很多。
-
3 # 拖延症_晚期_
就是gil導致這貨只能跑一個執行緒,無法充分利用cpu。題主說的場景,語言解釋性是次要的,可以忽略。python真正多執行緒只能透過呼叫c庫。gevent,libuv等實現。所以當年那些人工智慧庫只是為了語法簡單就選了python,真的是一個很二的選擇。
-
4 # 自可樂
我們一般使用的 Python 是 CPython,導致它慢的原因主要有下面三條:
它是動態型別語言
它是解釋型語言而非編譯語言它有 GIL(Global Interpreter Lock全域性直譯器鎖)動態特性導致 Python中的變數沒有型別宣告,在執行過程中隨時可能改變其型別,因此其很難被最佳化,而且還會有變數型別變動帶來的記憶體釋放及重新分配的效能損失。
Python 是一種解釋型的語言,不像 C/C++ 等編譯型語言會直接將程式碼編譯誠機器嗎執行,另外 Python 也沒有像 Java 那樣的即時編譯工具(JIT)。
GIL 限制限制 Python 直譯器在一個時刻只能有一個執行緒執行,執行緒的排程和切換也會損失一些效能。
要提高 Python 的執行效能,可以針對以上幾條限制下功夫:
使用 Cython 為 Python 程式碼新增一些型別宣告,並將其靜態編譯成可供 Python 呼叫的擴充套件模組。
使用 Numba 對 Python 程式碼做即時編譯。開啟 GIL。方式有很多,比如說一些庫如 numpy 的很多操作都是打開了 GIL 的,我們在程式中呼叫這些庫中的相應操作就能開啟 GIL,另外也可以使用 Cython 的 with nogil 語句手動地開啟 GIL。使用多程序以避開 GIL 的限制。比如說可以使用標準庫中的 multiprocessing 模組,或者使用像 mpi4py 這樣的包進行多程序的平行計算。使用平行計算是加速 Python 的非常有效的方式。用 Python 做平行計算的途徑有很多,比如說使用標準庫中的 [threading 模組](https://docs.python.org/2/library/threading.html)進行執行緒級別的並行,[multiprocessing 模組](https://docs.python.org/2/library/multiprocessing.html)進行程序級別的並行,[concurrent.futures 模組](https://docs.python.org/3/library/concurrent.futures.html)實現非同步並行,使用 [IPython.parallel 模組](https://ipython.org/ipython-doc/3/parallel/index.html)進行多種方式的並行,使用 [mpi4py 包](https://pypi.org/project/mpi4py/)進行 MPI 訊息傳遞平行計算,等等。如果可以使用 C/C++,Fortran 或者使用 cython 為 Python 編寫擴充套件模組,還可以使用 OpenMP 並行。對 GPU 程式設計則可以使用 [pyCUDA](https://documen.tician.de/pycuda/)。我的個人[簡書專題](https://www.jianshu.com/c/5019bb7bada6)和 [CSDN 部落格專欄](https://blog.csdn.net/column/details/26248.html)中有對用 Python 做平行計算的專門介紹並提供了大量的程式例項。有需要或者感興趣的可以瞭解下。
-
5 # 晴月浩新雪
所謂慢,也只是因為CPython的實現相對保守一點罷了,又不是沒有別的選擇?更可況Python大多數時候是作為簡單易用的膠水語言來使用,負載高的底層計算模組的實現,完全可以用效率高的C語言,用Python隨便擺弄一下上層邏輯就好了,無傷大雅。
以時下比較火爆、所需計算負載高得驚人的人工智慧領域為例,無論是機器學習框架還是資料處理程式,Python都是當之無愧的主角,要是真的慢,早就一臉嫌棄的被拋棄了……
回覆列表
這意味著在程式執行時,直譯器不知道定義的變數的型別。 此圖表總結了C變數(我使用C作為編譯語言的替代)和Python變數之間的區別:
cint vs pyint對於C中的變數,編譯器透過其定義知道型別。 對於Python中的變數,在程式執行時你所知道的只是它是某種Python物件。
因此,如果您在C中編寫以下內容:
C編譯器從一開始就知道a和b是整數:它們根本不可能是其他任何東西! 有了這些知識,它可以呼叫新增兩個整數的例程,返回另一個整數,這只是記憶體中的一個簡單值。 作為粗略的原理圖,事件序列如下所示:
C加法
將<int> 1分配給a
將<int> 2分配給b
呼叫binary_add <int,int>(a,b)
將結果分配給c
Python中的等效程式碼如下所示:
這裡直譯器只知道1和2是物件,但不知道它們是什麼型別的物件。因此,直譯器必須檢查每個變數的PyObject_HEAD以找到型別資訊,然後為這兩種型別呼叫適當的求和例程。最後,它必須建立並初始化一個新的Python物件來儲存返回值。事件序列看起來大致如下:
Python加法
將1分配給a
1A。將a-> PyObject_HEAD-> typecode設定為整數
1B。設定a-> val = 1
將2分配給b
2A。將b-> PyObject_HEAD-> typecode設定為整數
2B。設定b-> val = 2
呼叫binary_add(a,b)
3A。在a-> PyObject_HEAD中找到typecode
3B。 a是整數;值是a-> val
3C。在b-> PyObject_HEAD中找到typecode
3D。 b是整數;值是b-> val
3E。呼叫binary_add <int,int>(a-> val,b-> val)
3F。結果是結果,並且是整數。
建立一個Python物件c
4A。將c-> PyObject_HEAD-> typecode設定為整數
4B。設定c-> val結果
所有動態型別都意味著任何操作都涉及更多步驟,這是Python與數值資料操作相比較慢的主要原因。