附錄A 高階Numpy
A.9 性能技巧
利用NumPy從代碼中獲得良好性能通常很簡單牵寺,因?yàn)閿?shù)組操作通常會取代相對緩慢的純Python循環(huán)攀涵。以下列表簡要總結(jié)了一些需要注意的事項(xiàng):
· 將Python循環(huán)和條件邏輯轉(zhuǎn)換為數(shù)組操作和布爾數(shù)組操作
· 盡可能使用廣播
· 使用數(shù)組視圖(切片)來避免復(fù)制數(shù)據(jù)
· 使用ufunc和ufunc方法
如果在用盡NumPy提供的功能之后仍然無法獲得所需的性能,請考慮在C厨埋、Fortran或Cython中編寫代碼。我在自己工作中經(jīng)常會使用Cython進(jìn)行一些微小開發(fā),這是一種獲得近乎C語言性能的方式久又。
A.9.1 連續(xù)內(nèi)存的重要性
?????? 盡管本主題的完整內(nèi)容超出了本書的范圍,但在某些應(yīng)用中效五,數(shù)組的內(nèi)存布局會顯著影響計算速度地消。這種情況是基于CPU的緩存層次結(jié)構(gòu)相關(guān)的性能差異。訪問連續(xù)內(nèi)存塊的操作(例如畏妖,將C順序數(shù)組的行相加)通常是最快的脉执,因?yàn)榇鎯ζ髯酉到y(tǒng)會將適當(dāng)?shù)拇鎯ζ鲏K緩沖到超快的L1或L2 CPU緩存中。此外戒劫,NumPy的C代碼庫中的某些代碼路徑已進(jìn)行優(yōu)化半夷,在連續(xù)內(nèi)存的情況下可以避免對通用跨步內(nèi)存的訪問。
?????? 如果說數(shù)組的內(nèi)存布局是連續(xù)的迅细,就意味著這些元素按照它們在Fortran順序(列方向)或C順序(行方向)排序中出現(xiàn)在數(shù)組中的次序存儲在內(nèi)存中巫橄。默認(rèn)情況下,NumPy數(shù)組創(chuàng)建為C順序連續(xù)或只是簡單連續(xù)茵典。因此湘换,一個列方向的數(shù)組,例如C順序數(shù)組的轉(zhuǎn)置數(shù)組,可以稱為是Fotran順序連續(xù)的彩倚。這些屬性都是可以通過ndarray的flags屬性來檢查的(見圖A-1)
?????? 在這個例子中筹我,對這些數(shù)組的行及逆行加和,在理論上arr_c是比arr_f更快署恍,這是因?yàn)閍rr_c的行在內(nèi)存中是連續(xù)的崎溃。這里我使用IPython中的%timeit進(jìn)行檢查(見圖A-2)
?????? 當(dāng)你想從NumPy中擠出更多的性能時,往往需要投入一些努力盯质。如果你的數(shù)組沒有所需的內(nèi)存順序袁串,則可以使用copy并傳遞’C’或’F'(見圖A-3)