4 回答

TA貢獻1824條經驗 獲得超8個贊
您的代碼的兩個版本都是矢量化的。您為嘗試向量化第二個版本而創建的數組只是開銷。
NumPy 向量化不是指硬件向量化。如果編譯器足夠聰明,它最終可能會使用硬件矢量化,但 NumPy 并沒有明確使用 AVX 或任何東西。
NumPy 向量化是指編寫一次對整個數組進行操作的 Python 級代碼,而不是使用一次對多個操作數進行操作的硬件指令。它是 Python 級別的向量化,而不是機器語言級別的向量化。與編寫顯式循環相比,這樣做的好處是 NumPy 可以在 C 級循環而不是 Python 中執行工作,從而避免了大量的動態調度、裝箱、拆箱、遍歷字節碼評估循環等。
從這個意義上說,您的代碼的兩個版本都是矢量化的,但是第二個版本在寫入和讀取巨大的數組時浪費了大量內存和內存帶寬。
此外,即使我們談論的是硬件級矢量化,該1 -
版本也與其他版本一樣適用于硬件級矢量化。您只需將標量加載1
到向量寄存器的所有位置并正常進行。與第二個版本相比,它涉及的內存傳輸要少得多,因此可能仍然比第二個版本運行得更快。

TA貢獻1811條經驗 獲得超6個贊
時間基本相同。正如其他人指出的那樣,沒有任何類型的硬件或多核并行化,只是解釋 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函數上:
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),所有這些都沒有復制。

TA貢獻1847條經驗 獲得超7個贊
我當然不是 numpy 專家,但我的猜測是第一個例子只使用一個向量,第二個例子首先創建了一個 1 的向量,然后減去。后者需要雙倍的內存和一個額外的步驟來創建 1 的向量。
在 x86 CPU 上,兩者都可能是某種 AVX 指令,一次可以處理 4 個數字。當然,除非您使用的是 SIMD 寬度大于向量長度的花哨 CPU,并且該 CPU 由 numpy 支持。

TA貢獻1848條經驗 獲得超10個贊
案例 A 在 mpu 上僅運行一個迭代器,而案例 B 在兩個與 X 一樣大的向量上具有兩個迭代器,如果未優化,則需要在線程中進行大量上下文切換。案例 B 是案例 A 的更通用版本......
添加回答
舉報