NumPy是Python中眾多科學軟件包的基礎。它提供了一個特殊的數據類型ndarray,其在向量計算上做了優化。這個對象是科學數值計算中大多數算法的核心。
相比于原生的Python,利用NumPy數組可以獲得顯著的性能加速,尤其是當你的計算遵循單指令多數據流(SIMD)范式時。然而,利用NumPy也有可能有意無意地寫出未優化的代碼。
在這篇文章中,我們將看到一些技巧,這些技巧可以幫助你編寫高效的NumPy代碼。我們首先看一下如何避免不必要的數組拷貝,以節省時間和內存。因此,我們將需要深入NumPy的內部。
學習避免不必要的數據拷貝
NumPy數組計算可能涉及到內存塊之間的內部拷貝。有時會有不必要的拷貝,此時應該避免。相應地這里有一些技巧,可以幫助你優化你的代碼。
import numpy as np
查看數組的內存地址
1. 查看靜默數組拷貝的第一步是在內存中找到數組的地址。下邊的函數就是做這個的:
def id(x): # This function returns the memory # block address of an array. return x.__array_interface__['data'][0]
2. 有時你可能需要復制一個數組,例如你需要在操作一個數組時,內存中仍然保留其原始副本。
a = np.zeros(10); aid = id(a); aid71211328b = a.copy(); id(b) == aidFalse
具有相同數據地址(比如id函數的返回值)的兩個數組,共享底層數據緩沖區。然而,共享底層數據緩沖區的數組,只有當它們具有相同的偏移量(意味著它們的第一個元素相同)時,才具有相同的數據地址。共享數據緩沖區,但偏移量不同的兩個數組,在內存地址上有細微的差別,正如下邊的例子所展示的那樣:
id(a), id(a[1:])(71211328, 71211336)
在這篇文章中,我們將確保函數用到的數組具有相同的偏移量。下邊是一個判斷兩個數組是否共享相同數據的更可靠的方案:
def get_data_base(arr): """For a given Numpy array, finds the base array that "owns" the actual data.""" base = arr while isinstance(base.base, np.ndarray): base = base.base return base def arrays_share_data(x, y): return get_data_base(x) is get_data_base(y) print(arrays_share_data(a,a.copy()), arrays_share_data(a,a[1:]))False True
感謝Michael Droettboom指出這種更精確的方法,提出這個替代方案。
就地操作和隱式拷貝操作
3. 數組計算包括就地操作(下面第一個例子:數組修改)或隱式拷貝操作(第二個例子:創建一個新的數組)。
a *= 2; id(a) == aidTrue c = a * 2; id(c) == aidFalse
新聞熱點
疑難解答