在下面的快照的,我比較
- 速度修改經由切片分配
- 只是現有陣列返回一個新的修改陣列
看起來後者更快。爲什麼會這樣呢?
編輯:有建議更新,並使用numpy的真實矢量add()
,這是目前速度最快的一個版本。
在下面的快照的,我比較
看起來後者更快。爲什麼會這樣呢?
編輯:有建議更新,並使用numpy的真實矢量add()
,這是目前速度最快的一個版本。
x + 1
將創建一個新的數組。y[:] = x + 1
:創建一個新的數組,所有的數據複製到y
y = x + 1
:創建一個新的陣列和BIND域名y
這個新陣。np.add(x, 1, out=y)
:不要創建新陣列,它是最快的。下面是代碼:
x = np.zeros(1000000)
y = np.zeros_like(x)
%timeit x + 1
%timeit y[:] = x + 1
%timeit np.add(x, 1, out=y)
輸出:
100 loops, best of 3: 4.2 ms per loop
100 loops, best of 3: 6.83 ms per loop
100 loops, best of 3: 2.5 ms per loop
我不知道很多關於Python/numpy的內部,但這裏是我認爲正在發生的事情。通過查看代碼,我發現finline
比freturn
做得更多,因爲finline
具有freturn
所做的所有語句(x + 1.0
)以及更多。
也許這可以解釋這是怎麼回事:
>>> x = np.random.rand(N)
>>> y = np.zeros(N)
>>> super(np.ndarray, y).__repr__()
Out[33]: '<numpy.ndarray object at 0x24c9c80>'
>>> finline(x, y)
>>> y # see that y was modified
Out[35]:
array([ 1.92772158, 1.47729293, 1.96549695, ..., 1.37821499,
1.8672971 , 1.17013856])
>>> super(np.ndarray, y).__repr__()
Out[36]: '<numpy.ndarray object at 0x24c9c80>' # address of y did not change
>>> y = freturn(x)
>>> super(np.ndarray, y).__repr__()
Out[38]: '<numpy.ndarray object at 0x24c9fc0>' # address of y changed
所以基本上,我認爲finline
做更多的工作,因爲它必須遍歷y的元素和他們每個人的初始化由返回的數組x + 1.0
操作。另一方面,y = freturn(x)
可能只是將y
指針的值重新初始化爲等於由x + 1.0
操作初始化的數組的地址。
好吧,我想你說的內嵌版本正在做一個額外的副本,即在該RHS計算會產生一箇中間值,作爲一個單獨的步驟被分配給inline-y的內存?也許。我正在查看'dis.dis()'的輸出... – 2014-11-05 01:19:37
@cjrh,是的,在這種情況下會有一箇中間結果。爲了避免中間,你可以這樣做:'y [:] = x,y + = 1.0'。速度更快嗎? – 2014-11-05 01:23:34
@cjrh:是的。我認爲這有點像C++中複製和移動構造函數的區別。 – Praveen 2014-11-05 01:34:03
謝謝!我最終自己到達那裏,但無論如何都有一些要點:) – 2014-11-05 01:40:46