如何将附加参数传递给numba cfunc作为LowLevelCallable传递给scipy.integrate.quad

2024-09-28 22:26:19 发布

您现在位置:Python中文网/ 问答频道 /正文

文档discusses使用numba的cfuncs作为scipy.integrate.quadLowLevelCallable参数。我需要同样的附加参数。在

我基本上是想做这样的事情:

import numpy as np
from numba import cfunc
import numba.types
voidp = numba.types.voidptr
def integrand(t, params):
    a = params[0] # this is additional parameter
    return np.exp(-t/a) / t**2
nb_integrand = cfunc(numba.float32(numba.float32, voidp))(integrand)

但是,它不起作用,因为params应该是voidptr/void*,它们不能被转换成{}。我收到以下错误消息:

^{pr2}$

我没有找到任何关于如何从Numba中的void*提取值的信息。在C语言中,它应该类似于a = *((double*) params)-在Numba中可以做同样的事情吗?在


Tags: 文档import参数npparams事情typesnumba
1条回答
网友
1楼 · 发布于 2024-09-28 22:26:19

1。通过scipy.integrate.quad

^{} docs说:

If the user desires improved integration performance, then f may be a scipy.LowLevelCallable with one of the signatures:

double func(double x)

double func(double x, void *user_data)

double func(int n, double *xx)

double func(int n, double *xx, void *user_data)

The user_data is the data contained in the scipy.LowLevelCallable. In the call forms with xx, n is the length of the xx array which contains xx[0] == x and the rest of the items are numbers contained in the args argument of quad.

因此,要通过quadintegrand传递额外的参数,最好使用double func(int n, double *xx)签名。在

您可以将decorator写入被积函数,将其转换为LowLevelCallable,如下所示:

import numpy as np
import scipy.integrate as si
import numba
from numba import cfunc
from numba.types import intc, CPointer, float64
from scipy import LowLevelCallable


def jit_integrand_function(integrand_function):
    jitted_function = numba.jit(integrand_function, nopython=True)

    @cfunc(float64(intc, CPointer(float64)))
    def wrapped(n, xx):
        return jitted_function(xx[0], xx[1])
    return LowLevelCallable(wrapped.ctypes)

@jit_integrand_function
def integrand(t, *args):
    a = args[0]
    return np.exp(-t/a) / t**2

def do_integrate(func, a):
    """
    Integrate the given function from 1.0 to +inf with additional argument a.
    """
    return si.quad(func, 1, np.inf, args=(a,))

print(do_integrate(integrand, 2.))
>>>(0.326643862324553, 1.936891932288535e-10)

或者,如果不需要decorator,请手动创建LowLevelCallable,并将其传递给quad。在

2。包装被积函数

我不确定以下内容是否能满足您的要求,但您也可以包装您的integrand函数以获得相同的结果:

^{pr2}$

3。从voidptr转换为python类型

我认为这还不可能。从2016年的this discussion开始,voidptr似乎只是在这里向C回调传递一个上下文。在

The void * pointer case would be for APIs where foreign C code does not every try to dereference the pointer, but simply passes it back to the callback as way for the callback to retain state between calls. I don't think it is particularly important at the moment, but I wanted to raise the issue.

尝试以下方法:

numba.types.RawPointer('p').can_convert_to(
    numba.typing.context.Context(), CPointer(numba.types.Any)))
>>>None

似乎也不令人鼓舞!在

相关问题 更多 >