具有Numba-nopython模式的三对角矩阵算法
我正试着用nopython模式和numba写一篇文章。这是我的密码:具有Numba-nopython模式的三对角矩阵算法,python,python-3.x,performance,numpy,numba,Python,Python 3.x,Performance,Numpy,Numba,我正试着用nopython模式和numba写一篇文章。这是我的密码: @jit(nopython=True) def TDMA(a、b、c、d): n=len(d) x=np.零(n) w=np.零(n) #ac,bc,cc,dc=map(np.copy,(a,b,c,d))#复制数组 ac=np.副本(a) bc=np.副本(b) cc=np.copy(c) dc=np.副本(d) 对于范围(1,n)内的i: w[i]=ac[i-1]/bc[i-1] bc[i]=bc[i]-w[i]*cc[i
@jit(nopython=True)
def TDMA(a、b、c、d):
n=len(d)
x=np.零(n)
w=np.零(n)
#ac,bc,cc,dc=map(np.copy,(a,b,c,d))#复制数组
ac=np.副本(a)
bc=np.副本(b)
cc=np.copy(c)
dc=np.副本(d)
对于范围(1,n)内的i:
w[i]=ac[i-1]/bc[i-1]
bc[i]=bc[i]-w[i]*cc[i-1]
dc[i]=dc[i]-w[i]*dc[i-1]
x[n-1]=dc[n-1]/bc[n-1]
对于范围(n-2,-1,-1)内的k:
x[k]=(dc[k]-cc[k]*x[k+1])/bc[k]
返回np.array(x)
然后测试该解算器:
A=np.array([[5,2,0,0],[1,5,2,0],[0,1,5,2],[0,0,1,5]],float)
B=np.数组([[15]、[2]、[7]、[20]、浮点)
a=a.对角线(-1)
b=A.对角线()
c=A.对角线(1)
x1=np.linalg.solve(A,B)
x2=TDMA(a、b、c、b)
打印('默认情况下解算器,x1=',x1)
打印('按TDMA,x2=',x2)
但是,我的TDMA功能失败,出现打字机错误
:
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Cannot resolve setitem: array(float64, 1d, C)[int64] = array(float64, 1d, C)
File "<ipython-input-20-e25cda7246bd>", line 16:
def TDMA(a,b,c,d):
<source elided>
x[n-1] = dc[n-1]/bc[n-1]
^
与nopython
也不兼容。是否可以在nopython
模式下使用map
功能
我知道我的TDMA可能仍然很慢。那么,有没有一种使用python 3语言实现三对角矩阵算法的最快代码?问题是,您有2D数组,但索引和分配它们就像是1D数组一样。因此,在将它们传递给numba函数之前,您可以只
ravel()
它们。我不确定这是否真的是正确的——但为了这个答案,我假设它是正确的
另外,您不需要复制a
和c
,因为您不修改它们,实际上只需要复制b
和d
的第一个元素
因此,工作函数可能如下所示:
import numba as nb
import numpy as np
@nb.njit
def TDMA(a,b,c,d):
n = len(d)
x = np.zeros(n)
bc = np.zeros(len(b))
bc[0] = b[0]
dc = np.zeros(len(d))
dc[0] = d[0]
for i in range(1, n):
w = a[i - 1] / bc[i - 1]
bc[i] = b[i] - w * c[i - 1]
dc[i] = d[i] - w * dc[i - 1]
x[n - 1] = dc[n - 1] / bc[n - 1]
for k in range(n - 2, -1, -1):
x[k] = (dc[k] - c[k] * x[k + 1]) / bc[k]
return x
TDMA(a.ravel(), b.ravel(), c.ravel(), B.ravel())
你这样称呼它:
import numba as nb
import numpy as np
@nb.njit
def TDMA(a,b,c,d):
n = len(d)
x = np.zeros(n)
bc = np.zeros(len(b))
bc[0] = b[0]
dc = np.zeros(len(d))
dc[0] = d[0]
for i in range(1, n):
w = a[i - 1] / bc[i - 1]
bc[i] = b[i] - w * c[i - 1]
dc[i] = d[i] - w * dc[i - 1]
x[n - 1] = dc[n - 1] / bc[n - 1]
for k in range(n - 2, -1, -1):
x[k] = (dc[k] - c[k] * x[k + 1]) / bc[k]
return x
TDMA(a.ravel(), b.ravel(), c.ravel(), B.ravel())
因为我使用了ravel()
结果与np.linalg.solve
的形状不同:
by default solver, x1 = [[ 3.05427975]
[-0.13569937]
[-0.18789144]
[ 4.03757829]]
by TDMA, x2 = [ 3.05427975 -0.13569937 -0.18789144 4.03757829]
然而,我真的不会重新实现NumPy函数,除非您可以利用NumPy函数不知道的数据结构。NumPy是一个高性能的库,它已经使用了非常精细的实现,因此,对于非常小的数据集,或者如果您可以利用数据的某些事实(允许使用非常高性能的算法),临时重新实现可能会更快
我必须承认,我不知道“三对角矩阵算法”,但我知道一些(通常难以置信的快速数学库)实现了它。NumPy使用BLAS
但是,SciPy为特殊矩阵类型提供了一些(非常快速的)特殊线性代数解算器:
计算矩阵的逆inv(a[,overwrite\u a,check\u finite])
为方阵的未知x求解线性方程组a*x=bsolve(a,b[,sym_pos,lower,overwrite_a,…])
假设a是带状矩阵,求解x的方程a x=bsolve_banded(l_和_,ab,b[,overwrite_ab,…])
求解方程a x=bsolveh_banded(ab,b[,overwrite_ab,…])
solve cx=b for x,其中c是循环矩阵solve_循环(c,b[,奇异,tol,…])
假设a是三角形矩阵,求解方程a x=b for x求解_三角形(a,b[,trans,lower,…])
使用Levinson递归求解toeplitz系统
map
的问题:现任官员不包括map
。因此,您不能在Numbas nopython模式下使用map