python高效能程式設計第一章讀書筆記
計算機底層元件分為三大基本部分:計算單元、儲存單元以及兩者之間的連線。
計算單元:具有將接收到的任意輸入轉換成輸出的能力以及改變當前處理狀態的能力。CPU是最常見的計算單元。它的主要屬性是其每個週期能進行的運算元量以及每秒能完成多少個週期。第一個屬性通過每週期完成的指令數(IPC)來衡量。第二個屬性通過其時鐘速度來衡量。時鐘速度的提高,可以使得每秒進行更多的計算,提高該計算單元所有程式的執行速度。IPC的提高則在向量計算能力上有相當程度的影響。向量計算指的是一次提供多個數據給一個CPU並能同時被操作。這種型別的CPU指令被稱為SIMD(單指令多資料)。
由於時鐘速度和IPC提升陷入停滯,開始依靠超執行緒技術,亂序執行和多核架構來提高速度。超執行緒技術為主機的作業系統(OS)虛擬了第二個CPU,硬體邏輯則試圖將兩個指令執行緒交錯地插入單個CPU的執行單元。亂序執行允許編譯器檢測出一個線性程式中某部分可以不依賴於之前的工作,也就是說兩個工作能夠以各種順序執行或同時執行。使得當一些指令被阻塞(比如等待一次記憶體訪問),另一些指令得以執行。多核架構指的是給CPU增加更多的核心。但是不一定多核就會更快,阿姆達爾定律認為:如果一個可以執行在多核上的程式有某些執行路徑必須執行在單核上,那麼這些路徑就會成為瓶頸導致最終速度無法加快。
對於python來說,python的全域性直譯器鎖(GIL),確保Python程序一次只能執行一條指令,無論當前有多少個核心。使得無法使用多核,但是我們可以使用標準庫的multiprocessing,或numexpr、Cython技術,或分散式計算模型來避免。
儲存單元,用於儲存位元。比如主機板上的暫存器、RAM以及硬碟。所有這些不同型別的儲存單元主要區別在於讀寫資料的速度。且速度與讀寫方式有關,如順序讀取要比隨機讀取快得多。此外還有延時來表示裝置查詢資料所花費的時間。
比如說判斷一個數是否為質數,首先將number的值儲存在RAM中。為了計算sqrt_number和number_float,將該值傳入CPU中,理想情況下只需要傳一次,它將被儲存在CPU的L1/L2快取中,然後CPU進行兩次計算並將結果傳回RAM儲存。在迴圈部分,我們更希望一次就將number——float和多個i的值傳入CPU進行檢查。
Python虛擬機器抽象層的影響之一就是向量操作變得不是直接可用。而numpy這樣的外部庫可以通過增加向量化數學操作來幫助我們解決這個問題。
Python抽象還影響了任何需要為下一次計算儲存L1/L2快取中相關資料的優化。首先是python物件不再是記憶體中最優化的佈局。這是因為python是一種垃圾收集語言----記憶體會被自動分配並在需要時釋放。這會導致記憶體碎片並影響CPU快取的傳輸。
Python的優勢在於可以輕易呼叫其他系統,正確運用庫可以使python程式碼在速度上和c媲美。