You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开启parallel=True时Numba编译报‘key already in dictionary’错误求助

Numba parallel=True编译失败:AssertionError: key already in dictionary: '$np_typ_var.1'

使用Anaconda提供的Python 3.11版本编写了如下函数,当为@njit装饰器设置parallel=True选项时,Numba无法完成编译:

@njit(nopython=True, nogil=True, cache=True, parallel=True)
def corrected_jacobian_numba_icecore(age_top_sigma,
                             accu, tau, lid, dens, dens_firn,
                             depth, depth_inter, depth_mid,
                             age, airage, age_model, airage_model,
                             ice_equiv_depth,
                             agedens, icelayerthick,
                             corr_a, corr_tau, corr_lid,
                             chol_a, chol_tau, chol_lid,
                             sigmap_corr_a, sigmap_corr_tau, sigmap_corr_lid,
                             corr_a_age, corr_tau_depth, corr_lid_age):

    age_jac = np.zeros((1+len(corr_a)+len(corr_tau)+len(corr_lid), len(age)))
    age_jac[0, :] = age_top_sigma * np.ones(len(age))       
    airage_jac = np.zeros((1+len(corr_a)+len(corr_tau)+len(corr_lid), len(airage)))
    airage_jac[0, :] = age_top_sigma * np.ones(len(airage))       
    delta_depth_jac = np.zeros((1+len(corr_a)+len(corr_tau)+len(corr_lid), len(depth)))
#    delta_depth[0, :] = age_top_sigma * np.zeros(len(depth))  # useless

    for i in prange(len(corr_a)):

        corr_a_vec = np.zeros(len(corr_a))
        corr_a_vec[i] = 1.
    #Accu
        corr_vec = np.dot(chol_a, corr_a_vec)*sigmap_corr_a
        toto = np.interp((age_model[:-1]+age_model[1:])/2,
                                  corr_a_age, corr_vec)
        agedens_vec = - toto * agedens

    #Ice age
        age_vec = np.cumsum(np.concatenate((np.array([0]), depth_inter*agedens_vec)))
        age_jac[1+i,:] = age_vec

    #Air age
        airage_vec = np.interp(ice_equiv_depth, depth, age_vec)
        airage_jac[1+i, :] = airage_vec
        # delta_depth_vec = np.zeros_like(depth)
        # delta_depth_jac[1+i, :] = delta_depth_vec
            

        
    for i in prange(len(corr_tau)):
                        
        corr_tau_vec = np.zeros(len(corr_tau))
        corr_tau_vec[i] = 1.
        corr_vec = np.dot(chol_tau, corr_tau_vec)*sigmap_corr_tau
        tata = np.interp(depth_mid, corr_tau_depth, corr_vec)
        agedens_vec = -tata * agedens                
        age_vec = np.cumsum(np.concatenate((np.array([0]), depth_inter*agedens_vec)))
        age_jac[1+len(corr_a)+i, :] = age_vec
        
        thin_vec = -tata * dens/tau
        udepth_vec = np.cumsum(np.concatenate((np.array([0]), depth_inter*thin_vec)))
        delta_depth_vec = - np.interp(ice_equiv_depth, depth_mid,
                                      tau/dens) * (udepth_vec - \
                                    np.interp(ice_equiv_depth, depth, udepth_vec))
        airage_vec = np.interp(ice_equiv_depth, depth, age_vec) \
                        - np.interp(ice_equiv_depth, depth_mid, agedens) * \
                        delta_depth_vec
        airage_jac[1+len(corr_a)+i, :] = airage_vec
        delta_depth_jac[1+len(corr_a)+i, :] = delta_depth_vec

        #To be continued...                

    for i in prange(len(corr_lid)):

        age_vec = np.zeros_like(depth)
        age_jac[1+len(corr_a)+len(corr_tau)+i, :] = age_vec

        corr_lid_vec = np.zeros(len(corr_lid))
        corr_lid_vec[i] = 1.
        corr_vec = np.dot(chol_lid, corr_lid_vec)*sigmap_corr_lid
        lid_vec = np.interp(airage_model, corr_lid_age, corr_vec) * lid
        delta_depth_vec = dens_firn * lid_vec * \
                            np.interp(ice_equiv_depth, depth_mid, 
                                      tau/dens)
        airage_vec = - np.interp(ice_equiv_depth, depth_mid, 
                                  agedens) * delta_depth_vec
        airage_jac[1+len(corr_a)+len(corr_tau)+i, :] = airage_vec
        delta_depth_jac[1+len(corr_a)+len(corr_tau)+i, :] = delta_depth_vec

    return airage_jac, delta_depth_jac, age_jac

编译时出现的错误信息:

AssertionError: Failed in nopython mode pipeline (step: nopython rewrites)
key already in dictionary: '$np_typ_var.1'

解决方法

1. 升级Numba版本

这个错误是Numba的已知类型推断bug,在Numba 0.57及以上的稳定版本中已修复。可以通过以下命令升级:

conda update numba

或使用pip:

pip install --upgrade numba

2. 优化循环内临时数组的创建

在prange循环内重复创建结构相同的数组(如corr_a_vec、corr_tau_vec)会干扰Numba的并行类型推断。可将数组预分配到循环外部,循环内仅重置值:

示例修改第一个循环:

# 预分配数组到循环外
corr_a_vec = np.zeros(len(corr_a))
for i in prange(len(corr_a)):
    corr_a_vec[:] = 0.  # 重置为0
    corr_a_vec[i] = 1.
    # 后续逻辑保持不变
    corr_vec = np.dot(chol_a, corr_a_vec)*sigmap_corr_a
    toto = np.interp((age_model[:-1]+age_model[1:])/2, corr_a_age, corr_vec)
    agedens_vec = - toto * agedens
    # ...

同理修改另外两个prange循环的临时数组创建逻辑。

3. 暂时禁用cache选项

cache=True与parallel=True同时启用时,可能触发编译缓存冲突。可先去掉cache=True编译函数,确认通过后再重新开启缓存。

4. 拆分复杂的interp调用

循环内多次调用np.interp可能导致类型推断冲突,可将重复的interp逻辑提取为单独的@njit函数:

@njit
def interp_helper(x, xp, fp):
    return np.interp(x, xp, fp)

然后在主函数中替换所有np.interp为interp_helper调用。

内容的提问来源于stack exchange,提问作者user3118932

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:54:55