[英]Why is subtraction faster when doing arithmetic with a Numpy array and a int compared to using vectorization with two Numpy arrays?
我對為什么這段代碼感到困惑:
start = time.time()
for i in range(1000000):
_ = 1 - np.log(X)
print(time.time()-start)
執行速度比這個實現快:
start = time.time()
for i in range(1000000):
_ = np.subtract(np.ones_like(X), np.log(X))
print(time.time()-start)
我的理解是它應該是相反的,因為在第二個實現中我正在利用矢量化提供的加速,因為它能夠同時操作 X 中的元素而不是順序操作,這就是我假設第一個實現的方式功能。
有人可以為我解釋一下嗎,因為我真的很困惑? 謝謝!
您的代碼的兩個版本都是矢量化的。 您為嘗試向量化第二個版本而創建的數組只是開銷。
NumPy 矢量化不是指硬件矢量化。 如果編譯器足夠聰明,它可能最終會使用硬件矢量化,但 NumPy 並沒有明確使用 AVX 或任何東西。
NumPy 向量化是指編寫一次對整個 arrays 進行操作的 Python 級代碼,而不是使用一次對多個操作數進行操作的硬件指令。 它是 Python 級別的向量化,而不是機器語言級別的向量化。 這種寫顯式循環的好處是 NumPy 可以在 C 級循環中執行工作,而不是 Python,避免了大量的動態調度、裝箱、拆箱、通過字節碼評估循環等。
從這個意義上說,您的代碼的兩個版本都是矢量化的,但是第二個版本在寫入和讀取巨大的數組時浪費了一堆 memory 和 memory 帶寬。
此外,即使我們談論的是硬件級矢量化, 1 -
版本也與其他版本一樣適用於硬件級矢量化。 您只需將標量1
加載到向量寄存器的所有位置並照常進行。 與第二個版本相比,它涉及到 memory 的傳輸要少得多,因此可能仍然比第二個版本運行得更快。
時間基本相同。 正如其他人指出的那樣,沒有任何類型的硬件或多核並行化,只是解釋的 Python 和編譯的numpy
函數的混合。
In [289]: x = np.ones((1000,1000))
In [290]: timeit 1-np.log(x)
15 ms ± 1.94 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [291]: timeit np.subtract(np.ones_like(x), np.log(x))
18.6 ms ± 1.89 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
將np.ones_like
排除在計時循環之外:
In [292]: %%timeit y = np.ones_like(x)
...: np.subtract(y,np.log(x))
...:
...:
15.7 ms ± 441 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2/3 的時間花在log
function 中:
In [303]: timeit np.log(x)
10.7 ms ± 211 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [306]: %%timeit y=np.log(x)
...: np.subtract(1, y)
3.77 ms ± 5.16 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
如何生成1
的變化只是時序的一小部分。
使用“廣播”,使用標量和數組或數組和數組進行數學運算同樣容易。
1
,無論是標量(實際上是一個形狀為()
的數組),都被廣播到 (1,1) 然后到 (1000,1000),所有這些都沒有復制。
我當然不是 numpy 專家,但我的猜測是第一個例子只使用一個向量,第二個例子首先創建了一個向量 1,然后減去。 后者需要雙倍數量的 memory 和一個額外的步驟來創建向量 1。
在 x86 CPU 上,兩者可能都是某種 AVX 指令,一次處理 4 個數字。 當然,除非您使用的是 SIMD 寬度大於矢量長度的精美 CPU,並且此 CPU 受 numpy 支持。
案例 A 在 mpu 上僅運行一個迭代器,而案例 B 在兩個與 X 一樣大的向量上具有兩個迭代器,如果未優化,則需要在線程中進行大量上下文切換。 案例 B 是案例 A 的更通用版本...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.