1 回答

TA貢獻(xiàn)1804條經(jīng)驗 獲得超8個贊
我可以確認(rèn)你的結(jié)果(numpy 1.15 vs Cython 0.28.3 + gcc-5.4):
>>> %timeit sample.clip(b, -5, 5, a)
20.5 ms ± 230 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit np.clip(b, -5, 5, a)
11.7 ms ± 312 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
很難說為什么食譜的作者有其他時間:其他 numpy 版本或其他編譯器。在這種情況下,np.clip除了使用 SIMD 指令外,沒有太大的改進(jìn)空間。
但是,您的 Cython 代碼不是最佳的。您可以通過聲明內(nèi)存視圖是連續(xù)的 iedouble[::1]而不是double[:]. 這會產(chǎn)生一個 cythonized C 代碼,它更容易為編譯器優(yōu)化(有關(guān)更多信息,請參閱此SO-question):
cpdef clip2(double[::1] a, double min, double max, double[::1] out):
....
>>> %timeit sample.clip2(b, -5, 5, a)
11.1 ms ± 69.9 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
這大約與 numpy 版本一樣快。
但是,為了獲得最佳結(jié)果,我會推薦Numba:使用Numba獲得更好的性能比使用 Cython 容易得多(參見例如這個SO-question):
import numba as nb
@nb.njit
def nb_clip(a, min, max, out):
if min > max:
raise ValueError('min must be <= max')
if a.shape[0] != out.shape[0]:
raise ValueError('input and output arrays must be the same size!')
for i in range(a.shape[0]):
if a[i] < min:
out[i] = min
elif a[i] > max:
out[i] = max
else:
out[i] = a[i]
...
%timeit nb_clip(b, -5, 5, a)
4.7 ms ± 333 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Numba 和原始 Cython 版本之間的性能差異在這里是由于 clang(這是 Numba 用于編譯的)在這種特殊情況下能夠生成比 gcc 更好的匯編程序。當(dāng)我在 Cython 中切換到 clang-5.0 時,我可以匹配(甚至略微擊敗)Numba。
添加回答
舉報