NumPy ufunc通用函数与矢量化运算原理
请解释NumPy中的ufunc(通用函数)是什么,它与普通Python循环的性能差距有多大?如何自定义ufunc?说明np.vectorize和np.frompyfunc的区别,以及真正的矢量化与np.vectorize之间的本质差异。
回答
屠龙少年
ufunc:对ndarray逐元素操作并进行广播的C级函数。如np.add、np.sin等。核心是调用底层C循环,无Python解释器开销,比Python List快10-100倍。
# Python循环 vs ufunc
arr = np.arange(10**7)
%timeit arr * 2 # ~15ms (ufunc)
%timeit [x*2 for x in arr] # ~500ms
自定义ufunc:用np.frompyfunc()将Python函数转为ufunc,但仍有Python调用开销:
def my_func(x, y): return x + y if x > 0 else x - y
ufunc = np.frompyfunc(my_func, 2, 1)
np.vectorize vs np.frompyfunc:
np.vectorize封装了frompyfunc,但增加类型推断和otypes参数np.frompyfunc更底层,返回object类型数组- 两者都不是真正的矢量化——底层仍是Python循环调用
真正的矢量化:利用NumPy已有ufunc组合,避免Python级循环:
# 坏:np.vectorize
# 好:np.where(arr > 0, arr + 1, arr - 1) # 纯C级操作