讓我們從三個dtype=np.double
的數組開始。計時是在英特爾CPU上使用numpy 1.7.1進行的,編譯時使用icc
並鏈接到intel的mkl
。編號爲gcc
且沒有mkl
的numpy 1.6.1 AMD CPU也用於驗證時序。請注意,時序與系統規模的增加幾乎呈線性,並且不因numpy的功能發生了小的開銷if
陳述這些區別將在微秒不毫秒顯示:爲什麼numpy的einsum比numpy的內置函數更快?
arr_1D=np.arange(500,dtype=np.double)
large_arr_1D=np.arange(100000,dtype=np.double)
arr_2D=np.arange(500**2,dtype=np.double).reshape(500,500)
arr_3D=np.arange(500**3,dtype=np.double).reshape(500,500,500)
首先讓我們看看np.sum
功能:
np.all(np.sum(arr_3D)==np.einsum('ijk->',arr_3D))
True
%timeit np.sum(arr_3D)
10 loops, best of 3: 142 ms per loop
%timeit np.einsum('ijk->', arr_3D)
10 loops, best of 3: 70.2 ms per loop
鮑爾斯:
np.allclose(arr_3D*arr_3D*arr_3D,np.einsum('ijk,ijk,ijk->ijk',arr_3D,arr_3D,arr_3D))
True
%timeit arr_3D*arr_3D*arr_3D
1 loops, best of 3: 1.32 s per loop
%timeit np.einsum('ijk,ijk,ijk->ijk', arr_3D, arr_3D, arr_3D)
1 loops, best of 3: 694 ms per loop
外積:
np.all(np.outer(arr_1D,arr_1D)==np.einsum('i,k->ik',arr_1D,arr_1D))
True
%timeit np.outer(arr_1D, arr_1D)
1000 loops, best of 3: 411 us per loop
%timeit np.einsum('i,k->ik', arr_1D, arr_1D)
1000 loops, best of 3: 245 us per loop
以上所有都是np.einsum
的兩倍。這些應該是蘋果比較蘋果,因爲一切都是專門爲dtype=np.double
。我期望加快在這樣的操作:
np.allclose(np.sum(arr_2D*arr_3D),np.einsum('ij,oij->',arr_2D,arr_3D))
True
%timeit np.sum(arr_2D*arr_3D)
1 loops, best of 3: 813 ms per loop
%timeit np.einsum('ij,oij->', arr_2D, arr_3D)
10 loops, best of 3: 85.1 ms per loop
Einsum似乎是至少快兩倍,爲np.inner
,np.outer
,np.kron
,並且np.sum
無論axes
選擇。主要的例外是np.dot
,因爲它從BLAS庫調用DGEMM。那麼爲什麼np.einsum
速度更快,其他numpy功能是相同的?
的DGEMM情況下的完整性:
np.allclose(np.dot(arr_2D,arr_2D),np.einsum('ij,jk',arr_2D,arr_2D))
True
%timeit np.einsum('ij,jk',arr_2D,arr_2D)
10 loops, best of 3: 56.1 ms per loop
%timeit np.dot(arr_2D,arr_2D)
100 loops, best of 3: 5.17 ms per loop
主導理論是從@sebergs評論說np.einsum
可以利用SSE2,但numpy的的ufuncs之前,不會numpy的1.8(見change log)。我相信這是正確的答案,但不是能夠確認它。通過改變輸入數組的dtype並觀察速度差異以及不是每個人都遵守相同的定時趨勢這一事實,可以找到一些有限的證明。
BLAS庫與numpy鏈接的是什麼?它是多線程的嗎? –
帶AVX的多線程MKL BLAS。 – Daniel
順便提一句,很好的問題,以及很好的例子!這可能值得在郵件列表中詢問。它之前已經被覆蓋了(特別是關於'sum'),但是我驚訝的發現'einsum'比'outer','inner','kron'等要快兩倍。知道在哪裏會很有趣差異來自於。 –