【发布时间】:2020-01-08 15:06:19
【问题描述】:
使用 Python,我想构建一个方阵,其系数是在某些给定点评估的函数。矩阵是下三角矩阵,但在大小为 1000 的情况下,输入所有系数需要 200 多秒。这让我很惊讶,因为我已经处理过大小大于 100 万的方阵。
我猜想时间的损失来自定义矩阵所有非零系数的函数:它是四个项的乘积,每个项都涉及一个复幂(请参见下面的最小示例)。 如果有人可以帮助我,我会非常高兴:目的是在几秒钟内达到 100 万的规模(希望这是可行的......)。也许使用 ** 对于复数幂不是最优的;或者也许有一种更快的方法来填充下三角矩阵?任何帮助将不胜感激!
对于下面的代码,Ns 是方阵的大小。
import math
from math import *
import numpy as np
from numpy import exp, log, sqrt, cos, sin, arange
import time
tmps1 = time.time()
Ns = 100
h = 1/float(Ns)
Ns = int(Ns)
mu = 0.01
rn = -6.34
rc = 0.86
r1 = 1.32
r2 = 4.16
P = np.zeros((Ns + 1, 1))
for j in range(0, Ns + 1):
P[j] = r1 + j*(r2-r1)*h
kappan = 0.24
kappac = -0.24
kappa1 = 0.095
kappa2 = -0.095
z = complex(0.01,0.01)
def E(exponent,p):
return ( ( ((p-rn)/(2-rn))**((exponent)/(2*kappan)) )*( ((p-rc)/(2-rc))**((exponent)/(2*kappac)) )*( ((p-r1)/(2-r1))**((exponent)/(2*kappa1)) )*( ((r2-p)/(r2-2))**((exponent)/(2*kappa2)) ) )
def D(p,r):
return ( ( 1/(2*complex(0.0,1.0)*(z-mu/r1)) )*( ( 1/(2*(kappa1-complex(0.0,1.0)*(z-mu/r1))) )*( E(2*(kappa1-complex(0.0,1.0)*(z-mu/r1)),r)*E(2*complex(0.0,1.0)*(z-mu/r1),p) ) - ( 1/(2*kappa1) )*E(2*kappa1,r) ) )
A = np.zeros((Ns-1, Ns-1), dtype=np.complex_)
for j in range(1, Ns-1):
for k in range(1, j+1):
A[j,k] = D(P[j+1], P[k+1]) - D(P[j+1], P[k])
tmps2 = time.time()-tmps1
print "\n\nExecution time = %f\n\n" %tmps2
【问题讨论】:
-
你可以尝试向量化计算,而不是使用带有
numpy的显式for循环。 -
@GZ0 我不明白你的意思,你能详细说明一下吗?
-
This post 提供基本介绍。
-
您可以轻松地将代码加速 2 倍,方法是注意在第 2 次内部循环和每次后续迭代中,术语
D(P[j+1], P[k])的值等于术语D(P[j+1], P[k+1])的值上一次迭代。 -
下一步要注意,在内部循环中,只有函数
D()的第二个参数会发生变化。因此,您可以重构代码,使仅依赖于D()的第一个参数的所有子表达式仅计算一次(每次外循环迭代)。这应该会给您带来另外 30% 的性能提升。
标签: python matrix compiler-optimization