![](/img/trans.png)
[英]Faster alternative to numpy for manual element-wise operations on large arrays?
[英]Are element-wise operations faster with NumPy functions than operators?
我最近遇到了一篇很棒的帖子 ,其中一位用戶建議在處理NumPy數組時, numpy.sum
比Python的sum
更快。
這讓我想到,使用NumPy函數比運算符更快地對NumPy數組進行元素操作? 如果是這樣,那為什么會這樣呢?
請考慮以下示例。
import numpy as np
a = np.random.random(1e10)
b = np.random.random(1e10)
np.subtract(a, b)
是否比a - b
可靠得快?
不,不是很重要。
np.sum
比sum
更快的原因是, sum
實現為“天真地”迭代迭代(在本例中為numpy數組),調用元素' __add__
運算符(這會產生很大的開銷),而numpy執行sum
優化,例如利用它知道元素的類型(dtype)的事實,並且它們在存儲器中是連續的。
np.subtract(arr1, arr2)
和arr1-arr2
不是這種情況。 后者大致翻譯為前者。
不同之處在於可以覆蓋python中的減法運算符,因此numpy數組會覆蓋它以使用優化版本。 但是, sum
操作不可覆蓋,因此numpy提供了另一種優化版本。
並不是的。 你可以很容易地檢查時間。
a = np.random.normal(size=1000)
b = np.random.normal(size=1000)
%timeit np.subtract(a, b)
# 1000000 loops, best of 3: 1.57 µs per loop
%timeit a - b
# 1000000 loops, best of 3: 1.47 µs per loop
%timeit np.divide(a, b)
# 100000 loops, best of 3: 3.51 µs per loop
%timeit a / b
# 100000 loops, best of 3: 3.38 µs per loop
numpy函數實際上似乎有點慢。 我不確定這是否重要,但我懷疑這可能是因為在同一個實現之上的一些額外的函數調用開銷。
編輯:正如@unutbu所說,這可能是因為np.add
和朋友在必要時有額外的類型檢查開銷來將數組轉換為數組,所以像np.add([1, 2], [3, 4])
這樣的東西np.add([1, 2], [3, 4])
作品。
@ shx2給出了很好的答案。
我將略微擴展sum
與np.sum
:
sum
將通過一個數組,逐個獲取元素並將它們轉換為Python對象,然后將它們作為Python對象一起添加。 np.sum
將使用本機代碼中的優化循環對數組求和,而不對單個值進行任何轉換(正如shx2指出的那樣,這至關重要的是需要數組內容的同質性和連續性) 到目前為止,每個數組元素到Python對象的轉換是開銷的主要來源。
順便說一句,這也解釋了為什么使用Python的標准庫C數組類型進行數學運算是愚蠢的。 sum(list)
比sum(array.array)
要快得多 。
ab
轉換為函數調用a.__rsub__(b)
。 因此它使用屬於變量的方法(例如,如果a
是數組,則編譯numpy代碼)。
In [20]: a.__rsub__??
Type: method-wrapper
String Form:<method-wrapper '__rsub__' of numpy.ndarray object at 0xad27a88>
Docstring: x.__rsub__(y) <==> y-x
np.subtract(x1, x2[, out])
的文檔顯示它是一個ufunc
。 ufunc
經常使用像__rsub__
這樣的編譯操作,但可能會增加一些開銷以適應ufunc
協議。
在許多其他情況下, np.foo(x, args)
轉換為x.foo(args)
。
通常,如果函數和運算符最終調用編譯的numpy代碼來進行實際計算,則時序將非常相似,尤其是對於大型數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.