贝塞尔功能(来自scipy.pecial)可以与numba一起使用



我正在尝试优化包含具有numba的贝塞尔函数的函数的积分(scipy.integrate.quad)。

虽然numba似乎适用于"常见" numpy函数,但是当我尝试包含贝塞尔函数时,它会引发错误:

Untyped global name 'jn': cannot determine Numba type of <class 'numpy.ufunc'>

从一些谷歌搜索中,我从Numba存储库中找到了一个Jupyter笔记本,该笔记本讨论了制作J0功能(https://github.com/numba/numba/numba/numba/blob/08d55c8894949491212121321321328888bebebebebebebig ybigib bigin;20numba.ipynb)。

笔记本注释是,在NUMBA中制作功能会很快,但是它们在末尾显示的时序结果表明使用Numba速度慢了约100倍。我在这里错过了明显的东西吗?

,更一般地,是否可以从scipy bessel函数的numba汇编中受益?

通常是numpy和scipy提供非常快实现。另一方面,Numba根据Python函数自动生成代码。

因此,除了python函数之外,您都不能在任何东西上应用numba,并且如果您想要nopython模式(如果您对速度感兴趣,则想要它),甚至不是每个python函数。NUMBA仅支持一组非常有限的功能和类型。这些功能都在Numba中重新实现,即使看起来会看起来也不会使用python或numpy函数!

因此,您已经自动生成的LLVM代码与高度优化的自定义C/Fortran代码。因此,您不应该期望获得任何收益(尽管与Numpy/Scipy功能相比,Numba通常在很小的阵列中表现出色 - 但对于中型阵列,Numba的阵列也会慢)。

但是,如果您想在numba jitter函数内使用一些(当前不支持的)函数,则必须自己重新启动。除非在长期牢固地打电话时,它将不值得麻烦,只需使用正常功能即可。开发人员时间通常比运行时重要得多。

这并不意味着Numba并不好。对于需要许多计算/循环的任务非常有用,并且无法使用现有的numpy或Scipy函数实现。

这是您要寻找的代码:

# Bessel function of order 1 - note that smaller arguments are added first
@nb.jit(nopython = True, nogil = True, cache = False)
def Bessel1(z):
    if z.real <= 8.:
        t = z / 8.
        fz = z * (-0.2666949632 * t**14 + 1.7629415168000002 * t**12 + -5.6392305344 * t**10 + 11.1861160576 * t**8 + -14.1749644604 * t**6 + 10.6608917307 * t**4 + -3.9997296130249995 * t**2 + 0.49999791505)
    else:
        t = 8. / z
        eta = z - 0.75 * cmath.pi
        fz = cmath.sqrt(2 / (cmath.pi * z)) * ((1.9776e-06 * t**6 + -3.48648e-05 * t**4 + 0.0018309904000000001 * t**2 + 1.00000000195) * cmath.cos(eta) - (-6.688e-07 * t**7 + 8.313600000000001e-06 * t**5 + -0.000200241 * t**3 + 0.04687499895 * t) * cmath.sin(eta))
    return fz

我不记得这个特定实现的精度。请注意,我已经完成了您可能也可能也不需要的复数。

一年左右,我将其从一本旧的计算本教科书中取出。这有点像泰勒系列的扩展。我忘记了所谓的确切方法。

在代码中注意,必须首先添加" T"的高阶功率。这是因为T始终小于1,如果您将较小的浮点数添加到较大的浮点数,则舍入错误将更大。

最新更新