https://numpy.org/doc/1.18/reference/generation/numpy.vectorize.html
本教程提到vectorize的实现本质上是一个for循环。 但据我所知,矢量化函子将使用
SIMD,那么说numpy.vectorize的实现本质上是一个for循环是否准确? 如果为true,那么仅因为它是用C语言循环实现的,所以它比未向量化的func更快。
提前谢谢了。
是。 在Python(with numpy)和MATLAB™等解释型数值数组编程语言的上下文中,我们经常使用“向量化”来指代将解释型编程语言中的显式循环替换为负责所有操作的函数(或运算符)。内部循环逻辑。 在numpy中, ufunc
s实现了此逻辑。 这与“矢量化”的使用无关,后者是指使用SIMD CPU指令并发地计算多个输入,不同之处在于它们都使用类似的隐喻:它们就像它们的“标量”对应物一样,但是对多个输入值执行计算一次调用。
使用numpy.vectorize()
,与显式Python for
循环相比,通常没有太多的速度优势。 它的主要目的是将Python函数变成ufunc
,它实现了所有广播语义,因此可以处理任何大小的输入。 被“向量化”的Python函数仍然需要花费大部分时间,并将每个元素的原始值转换为Python对象以传递给该函数。 您不会期望np.vectorize(lambda x, y: x + y)
与ufunc np.add
一样快,在循环和循环内容中均为C。
感谢您的详细解释。 但是要明确一点,让我举一个例子。
import pandas as pd
import numpy as np
df = pd.DataFrame({'a': range(100000), 'b': range(1, 1000001)})
# method1
df.loc[:, 'c'] = df.apply(lambda x: x['a'] + x['b'], axis=1)
# method2
df.loc[:, 'c'] = np.vectorize(lambda x, y: x + y)(df['a'], df['b'])
# method3
df.loc[:, 'c'] = np.add(df['a'], df['b'])
所以我想你的解释
方法在C中循环| C中的循环内容使用SIMD
-| -| -| -
1 | ×| ×| ×
2 | √| ×| ×
3 | √| √| √
对?
np.add
比np.vectorize(lambda x, y: x + y)
更快,因为它避免了将C double转换为Python对象以及Python函数调用开销。 根据是否具有AVX2扩展,它可能还会使用SIMD指令,但这不是为什么它速度更快的原因。
np.add
比np.vectorize(lambda x, y: x + y)
更快,因为它避免了将C double转换为Python对象以及Python函数调用开销。 也可能会使用SIMD指令,具体取决于您是否具有AVX2扩展,但这不是为什么它更快的原因。
我知道了。 谢谢。
您可以使用numba的vectorize
来生成可并行运行的ufunc,而无需使用Python开销:
https://numba.pydata.org/numba-doc/latest/user/vectorize.html
最有用的评论
是。 在Python(with numpy)和MATLAB™等解释型数值数组编程语言的上下文中,我们经常使用“向量化”来指代将解释型编程语言中的显式循环替换为负责所有操作的函数(或运算符)。内部循环逻辑。 在numpy中,
ufunc
s实现了此逻辑。 这与“矢量化”的使用无关,后者是指使用SIMD CPU指令并发地计算多个输入,不同之处在于它们都使用类似的隐喻:它们就像它们的“标量”对应物一样,但是对多个输入值执行计算一次调用。使用
numpy.vectorize()
,与显式Pythonfor
循环相比,通常没有太多的速度优势。 它的主要目的是将Python函数变成ufunc
,它实现了所有广播语义,因此可以处理任何大小的输入。 被“向量化”的Python函数仍然需要花费大部分时间,并将每个元素的原始值转换为Python对象以传递给该函数。 您不会期望np.vectorize(lambda x, y: x + y)
与ufuncnp.add
一样快,在循环和循环内容中均为C。