有没有一种方法可以在数值python代码中最小化对new的调用次数?

2024-06-11 10:31:11 发布

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

我正在努力加速一些用python编写的数值建模代码。它依赖于numpy数组和scipy.linalg的矩阵求解方法。这是一个有限差分偏微分方程解算器。在分析和处理一些较慢的位之后,最大的时间块被built-in method __new__占用。__new__方法是否在每次声明数字时都执行?有什么办法可以避免吗?以下是解算器的主循环:

    #iterate over time steps
for j in range(1,N_t):

    #store some numbers
    jm1 = j - 1
    mm2 = m - 2
    mm1 = m - 1
    mp1 = m + 1
    pm1 = p - 1
    pm2 = p - 2

    #load the "b vector"
    vec[0] = v1*C[0,jm1] + v2*C[1,jm1]
    for i in r_vec_a:
        vec[i] = hlam_a*C[i-1,jm1] + v3*C[i,jm1] + hlam_a*C[i+1,jm1]
    vec[mm1] = -f1*C[mm2,jm1] + f5*C[mm1,jm1] - f3*C[m,jm1] - f4*C[mp1,jm1]
    vec[m] = -g1*C[mm2,jm1] - g2*C[mm1,jm1] + g5*C[m,jm1] - g4*C[mp1,jm1]
    for i in r_vec_b:
        vec[i] = hlam_b*C[i-1,jm1] + v4*C[i,jm1] + hlam_b*C[i+1,jm1]
    vec[pm1] = v5*C[pm2,jm1] + v6*C[pm1,jm1]

    #solve the matrix equation for new concentrations
    C[:,j] = scipy.linalg.solve_banded(u1, banded, vec, check_finite = u2,
        overwrite_b = u3)

    #compute boundary values (with 2 extra orders of accuracy because it's easy)
    C_x0[0,j] = w1*C[0,j] - w2*C[1,j] + w3*C[2,j] - w4*C[3,j]
    C_xL[0,j] = e1*C[mm2,j] + e2*C[mm1,j] + e3*C[m,j] + e4*C[mp1,j]
    C_yL[0,j] = K_r*C_xL[0,j]
    C_y0[0,j] = -w4*C[p-4,j] + w3*C[p-3,j] - w2*C[pm2,j] + w1*C[pm1,j]

我的第一个想法是存储所有索引变量和常量(如果它们被重用),但这并没有减少对__new__的调用。你知道吗


Tags: 方法innewforscipy算器veclinalg
1条回答
网友
1楼 · 发布于 2024-06-11 10:31:11

探查器应该告诉您正在调用哪个对象的__new__方法。你知道吗

代码中最突出的一点是,在solve_banded调用的幕后有相当多的复制。你知道吗

答案在solve_banded的来源中: https://github.com/scipy/scipy/blob/v0.17.1/scipy/linalg/basic.py#L180-L255

如果您的scipy版本是0.15.1或更低,它不会对三对角矩阵进行特殊处理,而是将您的输入复制到一个更大的LAPACK矩阵中(请参阅源代码中的not l==u==1分支)。你知道吗

因为您是在循环中进行操作,所以可能需要直接调用相关的LAPACK函数:只需内联solve_banded的相关部分。然后再做一次侧写。你知道吗

相关问题 更多 >