我正在尝试加速以下计算代码:
我只需要为 x > y 从 0 到 1 计算此函数(但需要非常高的离散化,如 dt = 0.001)。我已经矢量化了我的解决方案,但它仍然不够快(确实需要 10 倍的改进)。有任何想法吗? (尝试过类似 cython 的东西,但由于矢量化的性质,仍然很慢)
def solveF(x, f, lam):
nx = len(x)
res = np.zeros((nx, nx))
for i in range(0, nx):
for j in range(0, nx):
if i > j:
res[i][j] = f*np.exp(lam*(x[i]-x[j]))
return res
def fastKernelCalc(f, x, dx):
nx = len(x)
kappa = np.zeros((nx, nx))
f2 = f.transpose()
for i in range(nx):
t1 = time.time()
for j, xj in enumerate(x):
kernel = 0
if i-j>0 and j!=0:
kernel -= sum(np.diagonal(f, offset=j-i)[0:j])*dx
for k in range(0, j):
kernel += sum(f2[k][k:k+i-j]*kappa[i-j+k][k:k+i-j])*dx*dx
kappa[i][j] = kernel
return kappa
X = 1
dx = 0.001
nx = int(round(X/dx))+1
spatial = np.linspace(0, X, nx)
f = solveF(spatial, 5, 5)
kernel= fastKernelCalc(f, spatial, dx)
我的第一个想法是,如果速度是最重要的,那么您应该使用 C 或 Fortran 来处理数字内容。 Python 很棒,但速度不快。
弹出的东西:
在 solveF 的双循环中,你可以这样做
for j in range(0,i)
因为如果 j > i 你什么都不做。这不会为您节省很多时间,因为没有进行任何计算,但这是可以改进的。
你能不能重写你的方程,这样你就不用计算 f 的转置了?如果 f 很大,这可能是计算密集型的。
我不是 Python 专家,所以这可能很愚蠢,但我会避免使用“求和”和“对角线”。有时(对此持保留态度)这个通用函数必须进行大量检查以确保可以完成操作。
如果这是最重要的,并且值得付出努力,我会在代码的不同部分添加计时器,以确定哪部分是瓶颈。如果有瓶颈。
希望这有帮助。