python - Numba 数据类型错误 : Cannot unify array

标签 python performance numpy vectorization numba

我正在使用 Numba 来加速一系列功能,如下所示。如果我设置 step_size函数中的变量 PosMomentSingle到浮点数(例如 step_size = 0.5 ),而不是整数(例如 step_size = 1.0 ),我收到以下错误:

Cannot unify array(float32, 1d, C) and array(float64, 1d, C) for 'axle_coords.2', defined at <ipython-input-182-37c789ca2187> (12)

File "<ipython-input-182-37c789ca2187>", line 12:
def nbSimpleSpanMoment(L, axles, spacings, step_size):
    <source elided>
    
    while np.min(axle_coords) < L:
我发现很难理解问题是什么,但我猜测 @jit 之后的函数存在问题。 ( nbSimpleSpanMoment ),具有某种数据类型不匹配。我尝试将所有变量设置为 float32,然后设置为 float64(例如 L = np.float32(L) ),但无论我尝试什么都会产生一组新的错误。由于错误消息非常神秘,我无法调试问题。有 numba 经验的人可以解释我在这里做错了什么吗?
我把我的代码放在下面来重现这个问题。
感谢您的帮助!
import numba as nb
import numpy as np

@nb.vectorize(nopython=True)
def nbvectMoment(L,x):
    if x<L/2.0:
        return 0.5*x
    else:
        return 0.5*(L-x)

@nb.jit(nopython=True)
def nbSimpleSpanMoment(L, axles, spacings, step_size):
    travel = L + np.sum(spacings)
    maxmoment = 0
    axle_coords = -np.cumsum(spacings)
    moment_inf = np.empty_like(axles)
    while np.min(axle_coords) < L:
        axle_coords = axle_coords + step_size
        y = nbvectMoment(L,axle_coords)
        for k in range(y.shape[0]):
            if axle_coords[k] >=0 and axle_coords[k] <= L:
                moment_inf[k] = y[k]
            else:
                moment_inf[k] = 0.0   
        moment = np.sum(moment_inf * axles)
        if maxmoment < moment:
            maxmoment = moment
    return np.around(maxmoment,1)

def PosMomentSingle(current_axles, current_spacings):
    data_list = []
    for L in range (1,201):
        L=float(L)        
        if L <= 40:
            step_size = 0.5
        else:
            step_size = 0.5            
        axles = np.array(current_axles, dtype='f')
        spacings = np.array(current_spacings, dtype='f')            
        axles_inv = axles[::-1]
        spacings_inv = spacings[::-1]           
        spacings = np.insert(spacings,0,0)
        spacings_inv = np.insert(spacings_inv,0,0)            
        left_to_right = nbSimpleSpanMoment(L, axles, spacings, step_size)
        right_to_left = nbSimpleSpanMoment(L, axles_inv, spacings_inv, step_size)            
        data_list.append(max(left_to_right, right_to_left))
    return data_list

load_effects = []
for v in range(14,31):
    load_effects.append(PosMomentSingle([8, 32, 32], [14, v]))
load_effects = np.array(load_effects)

最佳答案

删除代码中的所有类型转换后,返回以下错误

TypingError: Cannot unify array(int64, 1d, C) and array(float64, 1d, C) for 'axle_coords.2'
这帮助我将错误追溯到 dtypespacings .在您的代码中,它初始化为 C 兼容 single ,这似乎与 python 不同 float32 ,见 here .将此更改为 np.float64 后代码现在运行。
下面的代码现在运行并且统一错误不再发生。
import numba as nb
import numpy as np

@nb.vectorize(nopython=True)
def nbvectMoment(L,x):
    if x<L/2.0:
        return 0.5*x
    else:
        return 0.5*(L-x)

@nb.jit(nopython=True)
def nbSimpleSpanMoment(L, axles, spacings, step_size):
    travel = L + np.sum(spacings)
    maxmoment = 0
    axle_coords = -np.cumsum(spacings)
    moment_inf = np.empty_like(axles)
    while np.min(axle_coords) < L:
        axle_coords = axle_coords + step_size
        y = nbvectMoment(L,axle_coords)
        for k in range(y.shape[0]):
            if axle_coords[k] >=0 and axle_coords[k] <= L:
                moment_inf[k] = y[k]
            else:
                moment_inf[k] = 0.0
        moment = np.sum(moment_inf * axles)
        if maxmoment < moment:
            maxmoment = moment
    return np.around(maxmoment,1)

def PosMomentSingle(current_axles, current_spacings):
    data_list = []
    for L in range (1,201):
        L=float(L)
        if L <= 40:
            step_size = 0.5
        else:
            step_size = 0.5
        axles = np.array(current_axles, np.float32)
        spacings = np.array(current_spacings, dtype=np.float64)
        axles_inv = axles[::-1]
        spacings_inv = spacings[::-1]
        spacings = np.insert(spacings,0,0)
        spacings_inv = np.insert(spacings_inv,0,0)
        left_to_right = nbSimpleSpanMoment(L, axles, spacings, step_size)
        right_to_left = nbSimpleSpanMoment(L, axles_inv, spacings_inv, step_size)
        data_list.append(max(left_to_right, right_to_left))
    return data_list

load_effects = []
for v in range(14,31):
    load_effects.append(PosMomentSingle([8, 32, 32], [14, v]))
load_effects = np.array(load_effects)

关于python - Numba 数据类型错误 : Cannot unify array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64639526/

相关文章:

python - re.compile 如何在 BeautifulSoup 中执行 find_all 函数?

c# - C#中内联方法的成本

Java(Java声音): Is "clip.play()" an expensive call?

python pandas dataframe if else 不遍历数据框

python - 使用分隔符 python 跟踪数组中的项目

python - python 中的泛型方法

python - 我安装了python 3.5.2(64位),pip版本是9.0.1,但是当我尝试安装tensorflow时,它说找不到版本,为什么是:(the

python - 在 Django Admin 中添加 map

c - 并行调用函数是否足以让它并行执行?

python - 在数组中操作 Numpy 数组的快速方法