Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在numba中的`@guvectorize`中调用`@guvectorize`?_Python_Numba - Fatal编程技术网

Python 如何在numba中的`@guvectorize`中调用`@guvectorize`?

Python 如何在numba中的`@guvectorize`中调用`@guvectorize`?,python,numba,Python,Numba,我试图在@guvectorize中调用@guvectorize,但我有一个错误: Untyped global name 'regNL_nb': cannot determine Numba type of <class 'numpy.ufunc'> File "di.py", line 12: def H2Delay_nb(S1, S2, R2): H1 = regNL_nb(S1, S2) ^ 我不知道如何告诉numba函数regNL_nb

我试图在
@guvectorize
中调用
@guvectorize
,但我有一个错误:

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

File "di.py", line 12:
def H2Delay_nb(S1, S2, R2):
    H1 = regNL_nb(S1, S2)
    ^
我不知道如何告诉numba函数regNL_nb是一个guvectorize函数

@guvectorize(["float64[:], float64[:],  float64[:]"], '(n),(n)->(n)',nopython=True)
def H2Delay_nb(S1, S2, R2):
    H1 = regNL_nb(S1, S2)
    H2 = regNL_nb(S1, S2,)
    for i in range(len(S1)):
        R2[i] =  H1[i] + H2[i]
通过使用参数
nopython=True
可以停用对象模式,因此Numba无法将所有值作为Python对象处理(请参阅:)

通常,如果使用
nopython=True
,Panda、Numba或其他函数调用是不可能的。只有有限数量的库可用于Numba Jit(在
nopython
中)。 可在此处找到完整列表:

因此,除了禁用
nopython
,您尝试执行的操作是不可能的,即:

@guvectorize(["float64[:], float64[:],  float64[:]"], '(n),(n)->(n)',nopython=False)
    def H2Delay_nb(S1, S2, R2):
        H1 = regNL_nb(S1, S2)
        H2 = regNL_nb(S1, S2,)
        for i in range(len(S1)):
            R2[i] =  H1[i] + H2[i]
按照这种方法,程序输出正确的值,即
[4.8.12.16.20.24.28.32.36.]
用于
H2

我还发现另一个StackOverflow问题涉及一个熟悉的问题:。积分到期时的积分:在提到的线程中建议您使用“更简单”的数据类型,这在CPython中最常见。除此之外,在这一点上我完全同意他的观点,我不知道在
nopython
模式下有任何可能的解决方案


来源:


我的答案仅适用于这种情况,如果您可以用@njit替换@guvectorize,那么它将是完全相同的代码,同样快,只是要使用更长的语法

在nopython模式下,接受其他guvectorize函数中的
@guvectorize
-ed函数可能存在一些问题

但是Numba在其他njited中接受非常好的常规的
@njit
-ed函数。因此,您可以重写您的函数以使用@njit,您的函数签名将与外部世界的@guvectorize ed保持相同@njit版本只需要额外使用
np.empty_like(…)
+返回内部函数

@guvectorize(["float64[:], float64[:],  float64[:]"], '(n),(n)->(n)',nopython=True)
def H2Delay_nb(S1, S2, R2):
    H1 = regNL_nb(S1, S2)
    H2 = regNL_nb(S1, S2,)
    for i in range(len(S1)):
        R2[i] =  H1[i] + H2[i]
为了提醒您-所有@njit ed函数都始终启用了nopython模式,因此您的njite代码将与guvectorize+nopython一样快

我还提供CUDA解决方案作为第二个代码段

您也可以只使用@njited内部助手函数,但外部助手函数可能仍然可以使用@guvectorize-ed。此外,如果您想要通用函数(接受任何输入),只需从njited定义中删除签名
“f8[:](f8[:],f8[:])”
,签名将在调用时自动解析

最终代码如下所示:

输出:

[ 4.  8. 12. 16. 20. 24. 28. 32. 36.]
CUDA是同一代码的变体,如果要自动创建并返回结果数组,则需要额外的函数包装器,因为CUDA代码函数不允许有返回值:

import numpy as np
from numba import guvectorize, float64, int64, njit, cuda, jit

@cuda.jit('void(f8[:], f8[:], f8[:])', cache = True)
def regNL_nb_cu(S1, S2, h2):
    for i in range(len(S1)):
        h2[i] = S1[i] + S2[i]
        
@njit('f8[:](f8[:], f8[:])', cache = True)
def regNL_nb(S1, S2):
    h2 = np.empty_like(S1)
    regNL_nb_cu(S1, S2, h2)
    return h2
        
@cuda.jit('void(f8[:], f8[:], f8[:])', cache = True)
def H2Delay_nb_cu(S1, S2, R2):
    H1 = regNL_nb(S1, S2)
    H2 = regNL_nb(S1, S2)
    for i in range(len(S1)):
        R2[i] =  H1[i] + H2[i]
        
@njit('f8[:](f8[:], f8[:])', cache = True)
def H2Delay_nb(S1, S2):
    R2 = np.empty_like(S1)
    H2Delay_nb_cu(S1, S2, R2)
    return R2

S1 = np.array([1,2,3,4,5,6,7,8,9], dtype = np.float64)
S2 = np.array([1,2,3,4,5,6,7,8,9], dtype = np.float64)
H2 = H2Delay_nb(S1, S2)
print(H2)

预期的输出应该是
[4.8.12.16.20.24.28.32.36.]
,对吗?是的。每个数字执行上述脚本的方式只有四次,除了将参数
nopython
设置为
False
,因此代码可能会返回到对象模式——除了警告之外,它工作正常<代码>>>打印(H2)给出输出:
[4.8.12.16.20.24.28.32.36.]
。是的,它是这样工作的,但速度较慢。关键是要保持nopython=True模式,这样代码运行得更快;尽管如果停用对象模式,并非所有值都将作为Python对象处理。(见附件)
import numpy as np
from numba import guvectorize, float64, int64, njit, cuda, jit

@cuda.jit('void(f8[:], f8[:], f8[:])', cache = True)
def regNL_nb_cu(S1, S2, h2):
    for i in range(len(S1)):
        h2[i] = S1[i] + S2[i]
        
@njit('f8[:](f8[:], f8[:])', cache = True)
def regNL_nb(S1, S2):
    h2 = np.empty_like(S1)
    regNL_nb_cu(S1, S2, h2)
    return h2
        
@cuda.jit('void(f8[:], f8[:], f8[:])', cache = True)
def H2Delay_nb_cu(S1, S2, R2):
    H1 = regNL_nb(S1, S2)
    H2 = regNL_nb(S1, S2)
    for i in range(len(S1)):
        R2[i] =  H1[i] + H2[i]
        
@njit('f8[:](f8[:], f8[:])', cache = True)
def H2Delay_nb(S1, S2):
    R2 = np.empty_like(S1)
    H2Delay_nb_cu(S1, S2, R2)
    return R2

S1 = np.array([1,2,3,4,5,6,7,8,9], dtype = np.float64)
S2 = np.array([1,2,3,4,5,6,7,8,9], dtype = np.float64)
H2 = H2Delay_nb(S1, S2)
print(H2)