Python/Numba:scipy.special.gammainc()的未知属性错误

2022-01-10 00:00:00 python numpy scipy anaconda numba

问题描述

使用@jit 装饰器运行代码时出现错误.似乎无法找到函数 scipy.special.gammainc() 的某些信息:

I am having an error when running code using the @jit decorator. It appears that some information for the function scipy.special.gammainc() can't be located:

Failed at nopython (nopython frontend)
Unknown attribute 'gammainc' for Module(<module 'scipy.special' from 'C:homeMinicondalibsite-packagesscipyspecial\__init__.pyc'>) $164.2 $164.3 = getattr(attr=gammainc, value=$164.2)

没有@jit 装饰器,代码将运行良好.也许需要一些东西才能使 scipy.special 模块的属性对 Numba 可见?

Without the @jit decorator the code will run fine. Maybe there is something required to make the attributes of the scipy.special module visible to Numba?

提前感谢您的任何建议、意见等.

Thanks in advance for any suggestions, comments, etc.


解决方案

问题是 gammainc 并不是 Numba 天生知道如何处理的一小部分函数之一(参见 http://numba.pydata.org/numba-doc/dev/reference/numpysupported.html) - 实际上没有任何 scipy 函数.这意味着你不能在nopython"模式下使用它,不幸的是——它只需要把它当作一个普通的 python 函数调用.

The problem is that gammainc isn't one of the small list of functions that Numba inherently knows how to deal with (see http://numba.pydata.org/numba-doc/dev/reference/numpysupported.html) - in fact none of the scipy functions are. This means you can't use it in "nopython" mode, unfortunately - it just has to treat it as a normal python function call.

如果您删除 nopython=True,它应该可以工作.然而,这并不是非常令人满意,因为它可能会更慢.如果没有看到您的代码,很难知道确切的建议.但是,总的来说:

If you remove nopython=True, it should work. However, that isn't hugely satisfactory, because it may well be slower. Without seeing your code it's difficult to know exact what to suggest. However, in general:

  • 循环(不包含诸如 gammainc 之类的东西)将被加速,即使没有 nopython.

  • loops (that don't contain things like gammainc) will be sped up, even without nopython.

gammainc 是一个ufunc",这意味着它可以轻松地一次应用于整个数组,并且无论如何都应该快速运行.

gammainc is a "ufunc", which means it can be readily applied to a whole array at a time, and should run quickly anyway.

你可以调用func.inspect_types()来查看它是否能够编译.

you can call func.inspect_types() to see it's been able to compile.

举个简单的例子:

from scipy.special import gammainc
import numba as nb
import numpy as np

@nb.jit # note - no "nopython"
def f(x):
  for n in range(x.shape[0]):
    x[n] += 1
  y = gammainc(x,2.5)
  for n in range(y.shape[0]):
    y[n] -= 1
  return y

f(np.linspace(0,20)) # forces it to be JIT'd and outputs an array

然后 f.inspect_types() 将这两个循环标识为提升循环",这意味着它们将被 JIT 处理并快速运行.gammainc 的位不是 JIT 的,而是一次应用于整个数组,因此也应该很快.

Then f.inspect_types() identifies the two loops as "lifted loops", meaning they'll be JIT'd and run quickly. The bit with gammainc is not JIT'd, but is applied to the whole array at once and so should be fast too.

相关文章