SORU
21 AĞUSTOS 2013, ÇARŞAMBA


Neden numpy'daha hızlı numpy daha einsum s'fonksiyonlar s?

Sağlar dtype=np.double üç dizi ile başlayın. Zamanlamaları ıntel CPU numpy 1.7.1 icc ile derlenmiş kullanılarak yapılan ve mkl ıntel bağlı. Bir AMD numpy 1.6.1 ile cpu mkl de zamanlama doğrulamak için kullanıldı olmadan gcc ile derlenmiş. Lütfen zamanlamaları ölçek doğrusal sistem boyutu ile neredeyse Not ve küçük yükü numpy fonksiyonları if bu fark mikrosaniye görünecektir ifadeleri değil milisaniye: katlanılan nedeniyle değil

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)

İlk sağlar np.sum fonksiyonuna bak:

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

Güçleri:

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

Dış ürün:

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

Yukarıdakilerin hepsi iki kat daha hızlı np.einsum ile. Bu her şeyi dtype=np.double özel olarak elma karşılaştırma için elma olmalıdır. Böyle bir operasyonu: hız beklerdim

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 en az iki kat daha hızlınp.inner, np.outer, np.kron, ve np.sum axes seçimi ne olursa olsun gibi görünüyor. Birincil istisna olarak adlandırdığı np.dot olmak BLAS kitaplığından DGEMM. Neden eşdeğer diğer numpy fonksiyonları np.einsum daha hızlı?

Bütünlüğü için DGEMM durumda

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

Lider teorisi np.einsum SSE2, buradan, yorum sebergs @ama numpy. ufuncs numpy 1.8 kadar (change log). Bu doğru cevap var, ama ben inanıyorumdeğilbunu teyit etmek mümkün. Bazı sınırlı kanıt giriş dizisi d tipi değiştirme ve hız farkı ve herkes zamanlamaları aynı eğilimleri gözlemliyor gerçeğini gözlemleyerek bulunabilir.

CEVAP
21 AĞUSTOS 2013, ÇARŞAMBA


Öncelikle, numpy listede bu konuda geçmişte bir çok tartışma oldu. Örneğin, bakın: http://numpy-discussion.10968.n7.nabble.com/poor-performance-of-sum-with-sub-machine-word-integer-types-td41.html http://numpy-discussion.10968.n7.nabble.com/odd-performance-of-sum-td3332.html

Bazı aşağı kaynar için gerçeği einsum yeni ve muhtemelen olmaya çalışmak daha iyi önbellek hizalama ve diğer hafıza erişimi sorunları, pek çok eski numpy fonksiyonları odaklanmak kolay taşınabilir bir uygulama üzerinde bir ağır getirilmiş. Ama yine de tahminde bulunuyorum.


Ancak, ne yaptığını bazıları oldukça bir "elma-elma" karşılaştırma değil.

@Jamie zaten dedi, sum diziler için daha uygun bir akü kullanır ne ek olarak

Örneğin, sum daha dikkatli giriş türünü kontrol etmek ve uygun bir akü kullanma hakkında. Örneğin, aşağıdakileri göz önünde bulundurun:

In [1]: x = 255 * np.ones(100, dtype=np.uint8)

In [2]: x
Out[2]:
array([255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
       255, 255, 255, 255, 255, 255, 255, 255, 255], dtype=uint8)

sum doğru olmasına dikkat edin:

In [3]: x.sum()
Out[3]: 25500

einsum yanlış sonuç verecektir ise:

In [4]: np.einsum('i->', x)
Out[4]: 156

Ama eğer bir daha az sınırlı kullanırsak dtype, hala beklediğiniz sonucu elde ederiz:

In [5]: y = 255 * np.ones(100)

In [6]: np.einsum('i->', y)
Out[6]: 25500.0

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Alfredo Garcia

    Alfredo Garc

    25 Mayıs 2007
  • androidandme

    androidandme

    10 Mart 2009
  • Michelle Phan

    Michelle Pha

    18 Temmuz 2006