Python 如何使用Numba对接受标量并返回向量的函数进行向量化?
我有一个函数,它接受两个标量并返回一个一维数组。例如:Python 如何使用Numba对接受标量并返回向量的函数进行向量化?,python,performance,parallel-processing,vectorization,numba,Python,Performance,Parallel Processing,Vectorization,Numba,我有一个函数,它接受两个标量并返回一个一维数组。例如: import numpy as np def linear_pattern(slope,length): pattern = slope*np.arange(length) return pattern 我的目标是能够一次对相同的标量值长度进行多个坡度,也就是说,我想运行 >>> linear_pattern(np.array([3,4]),10) array([[ 0., 3., 6., 9.,
import numpy as np
def linear_pattern(slope,length):
pattern = slope*np.arange(length)
return pattern
我的目标是能够一次对相同的标量值长度进行多个坡度
,也就是说,我想运行
>>> linear_pattern(np.array([3,4]),10)
array([[ 0., 3., 6., 9., 12., 15., 18., 21., 24., 27.],
[ 0., 4., 8., 12., 16., 20., 24., 28., 32., 36.]])
而不是
>>> linear_pattern(3,10)
array([ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27])
>>> linear_pattern(4,10)
array([ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36])
我正在使用来自Numba的装饰师来做这项工作。以下是我的实施:
from numba import float64, guvectorize
@guvectorize( [(float64, float64, float64[:])], '(),() -> (n)' )
def linear_pattern(slope,length,pattern):
pattern[:] = slope*np.arange(length)
但是,我在尝试运行以下示例时出错:
>>> pattern = np.zeros(10)
>>> linear_pattern(np.array([3,4]),10,pattern)
NameError: undefined output symbols: n
由于我将函数的输出设置为维度n
的向量,并且没有定义该维度,即我没有在输入维度的任何地方使用n
,因此错误会出现。但是,输入都是标量,这就排除了使用n
我的问题是:
我如何才能使上述代码工作
由于length
始终是相同的标量,我更希望它是linear_pattern
的kwarg,而不是arg,然而,decoratorguvectorize
似乎不接受带有kwarg类型参数的函数。guvectorize
可以接受kwarg参数吗
暂时,我通过定义一个与输出维度相同的伪变量\uu
使代码正常工作。见下文:
length = 10
__ = np.zeros(length)
@guvectorize( [(float64, float64, float64[:], float64[:])], '(),(),(n) -> (n)' )
def linear_pattern(slope,length,__,pattern):
pattern[:] = slope*np.arange(length)
>>> pattern = np.zeros(length)
>>> linear_pattern(np.array([3,4]),length,pattern)
array([[ 0., 3., 6., 9., 12., 15., 18., 21., 24., 27.],
[ 0., 4., 8., 12., 16., 20., 24., 28., 32., 36.]])
编辑1:
在我最初的问题中,我使用了需要矢量化的实际函数的简化版本。原来的一个有更多的参数,也需要响应矢量化
以下面修改过的函数为例
def linear_pattern(slope, intercept, length):
pattern = slope*np.arange(length) + intercept
return pattern
然后我想跑步
slopes = np.array([3, 4])
intercepts = np.array([0, 1, 2])
length = 10
linear_pattern(slopes, intercepts, length)
结果具有尺寸(len(斜率)、len(截距)、长度)
,在这种情况下,它是(2,3,10)
。请注意,length
始终是一个固定整数,并且不需要对该参数进行矢量化,事实上,理想的解决方案是将length
保留为kwarg类型参数。如果您不介意线性模式
返回矩阵,您可以使用NumPy的广播(无需Numba):
输出:
[[03 6 9 12 15 18 21 24 27]]
[[ 0 3 6 9 12 15 18 21 24 27]
[ 0 4 8 12 16 20 24 28 32 36]]
这是怎么回事
np.arange(10).重塑((1,-1))
isarray([[0,1,2,3,4,5,6,7,8,9]])
数组([[3],[4]])
的元素级(!)乘法如下:
如果您不介意linear\u pattern
返回矩阵,您可以使用NumPy的广播(不需要Numba):
输出:
[[03 6 9 12 15 18 21 24 27]]
[[ 0 3 6 9 12 15 18 21 24 27]
[ 0 4 8 12 16 20 24 28 32 36]]
这是怎么回事
np.arange(10).重塑((1,-1))
isarray([[0,1,2,3,4,5,6,7,8,9]])
数组([[3],[4]])
的元素级(!)乘法如下:
如果你真的需要使用Numba,临时解决方案会存在很长时间。事实上,使用虚拟输入是可行的,因为根据,输出数组实际上是由NumPy的分派机制分配的,该机制调用Numba生成的代码 现在您需要分配一个虚拟输入,
length
参数是多余的。相反,您可以分配完整的输出:
@nb.guvectorize([(nb.float64, nb.float64[:], nb.float64[:])], '(),(n) -> (n)')
def linear_pattern2(slope, __, pattern):
pattern[:] = slope * np.arange(len(pattern))
>>> pattern = np.empty((2, length))
>>> linear_pattern2(np.array([3, 4]), pattern2)
array([[ 0., 3., 6., 9., 12., 15., 18., 21., 24., 27.],
[ 0., 4., 8., 12., 16., 20., 24., 28., 32., 36.]])
您可以使用out
kwarg(由Numpy的ufunc规范自动提供)防止不必要的输出阵列分配,这可能与大型阵列相关:
>>> pattern = np.empty((2, length))
>>> linear_pattern2(np.array([3, 4]), pattern, out=pattern)
>>> pattern
array([[ 0., 3., 6., 9., 12., 15., 18., 21., 24., 27.],
[ 0., 4., 8., 12., 16., 20., 24., 28., 32., 36.]])
函数的返回和输入数组是同一个对象:
>>> pattern = np.empty((2, length))
>>> lp = linear_pattern2(np.array([3, 4]), pattern, out=pattern)
>>> lp is pattern
True
如果你真的需要使用Numba,临时解决方案会存在很长时间。事实上,使用虚拟输入是可行的,因为根据,输出数组实际上是由NumPy的分派机制分配的,该机制调用Numba生成的代码 现在您需要分配一个虚拟输入,
length
参数是多余的。相反,您可以分配完整的输出:
@nb.guvectorize([(nb.float64, nb.float64[:], nb.float64[:])], '(),(n) -> (n)')
def linear_pattern2(slope, __, pattern):
pattern[:] = slope * np.arange(len(pattern))
>>> pattern = np.empty((2, length))
>>> linear_pattern2(np.array([3, 4]), pattern2)
array([[ 0., 3., 6., 9., 12., 15., 18., 21., 24., 27.],
[ 0., 4., 8., 12., 16., 20., 24., 28., 32., 36.]])
您可以使用out
kwarg(由Numpy的ufunc规范自动提供)防止不必要的输出阵列分配,这可能与大型阵列相关:
>>> pattern = np.empty((2, length))
>>> linear_pattern2(np.array([3, 4]), pattern, out=pattern)
>>> pattern
array([[ 0., 3., 6., 9., 12., 15., 18., 21., 24., 27.],
[ 0., 4., 8., 12., 16., 20., 24., 28., 32., 36.]])
函数的返回和输入数组是同一个对象:
>>> pattern = np.empty((2, length))
>>> lp = linear_pattern2(np.array([3, 4]), pattern, out=pattern)
>>> lp is pattern
True
我不介意
线性模式
返回矩阵。但是,我需要将向量化应用于一个函数,该函数具有多个需要接受向量化的参数。请参见我问题中的编辑1。我试图在编辑1中以修改后的linear\u pattern
形式使用“.reformate((1,-1))”,但是没有得到预期的结果。我认为使用Numba可以将矢量化扩展到所需的任意多个参数。我不介意线性模式
返回矩阵。但是,我需要将向量化应用于一个函数,该函数具有多个需要接受向量化的参数。请参见我问题中的编辑1。我试图在编辑1中以修改后的linear\u pattern
形式使用“.reformate((1,-1))”,但是没有得到预期的结果。我认为使用Numba可以根据需要将矢量化扩展到尽可能多的参数。