我有一个耦合常微分方程的系统
dx/dt = (A + C_d(t) * B) * x
,
其中A和B是常数矩阵,C_d是对角线系数矩阵,它根据积分变量的当前值平滑地变化。
方形矩阵A和B由较小的60 * 60上三角或零矩阵构成。整个系统的尺寸约为2500 * 2500。 A和B是稀疏的,具有~10%的非零元素。对角元素为负或零。主要(物理)约束是在集成期间不允许x(t)的元素变为负数。
目前,我雇用了一个'天真'的步骤解算器
x_(i+1) = A * x_i * dt_i + B * (C_d(t_i) * x_i) * dt_i + x_i
或者在CPU / GPU版本中
def solve_CPU(nsteps, dt, c_d, x):
for step in xrange(nsteps):
x += (A.dot(x) + B.dot(x * c_d[step])) * dt[step]
def solve_GPU(m, n, nsteps, dt, c_d, cu_curr_x, cu_delta_x, cu_A, cu_B):
for step in xrange(nsteps):
cubl.gemv(trans='T', m=m, n=n, alpha=1.0, A=cu_A,
x=cu_curr_x, beta=0.0, y=cu_delta_x)
cubl.gemv(trans='T', m=m, n=n, alpha=c_d[step], A=cu_B,
x=cu_curr_x, beta=1.0, y=cu_delta_x)
cubl.axpy(alpha=dt[step], x=cu_delta_x, y=cu_curr_x)
并利用一个特征,步长dt_i
这可以计算一个小修道院,其方式是x的元素在整合期间总是> = 0。根据近似值和设置,积分步骤的数量在25k到10M之间变化。
我尝试了几种优化通用硬件性能的方法:
代码是用Python编写的,可以通过Anaconda,Numba,Accelerate,Numpy等访问上面列出的库.SCIPY的稀疏BLAS例程与Anaconda中的MKL没有正确的链接,而cuSPARSE的Python包装据我所知不可用然而。我知道如何通过直接连接到cuSPARSE / C-MKL稀疏点产品来挤出更多性能,但就是这样。如果模型发生变化,这个练习必须一次又一次地解决,因此性能总是一个问题。我不是这方面的专家,所以我对预处理器,分解定理等知之甚少。是什么让我想到了我的问题:
有没有更优雅或更好的方法来解决这种线性代数任务?