求解大系统耦合微分方程

时间:2014-01-19 00:38:19

标签: matrix scipy linear-algebra sparse-matrix numerical-methods

我有一个耦合常微分方程的系统
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之间变化。

我尝试了几种优化通用硬件性能的方法:

  • (未知)使用ODEPACK的VODE解算器时,我不知道如何表达x> = 0约束
  • (最慢)使用英特尔MKL的密集BLAS 2点积
  • (中)在NVIDIA GPU上使用单精度cuBLAS的密集BLAS
  • (最快)使用CSR / CSC格式的SCIPY稀疏模块

代码是用Python编写的,可以通过Anaconda,Numba,Accelerate,Numpy等访问上面列出的库.SCIPY的稀疏BLAS例程与Anaconda中的MKL没有正确的链接,而cuSPARSE的Python包装据我所知不可用然而。我知道如何通过直接连接到cuSPARSE / C-MKL稀疏点产品来挤出更多性能,但就是这样。如果模型发生变化,这个练习必须一次又一次地解决,因此性能总是一个问题。我不是这方面的专家,所以我对预处理器,分解定理等知之甚少。是什么让我想到了我的问题:

有没有更优雅或更好的方法来解决这种线性代数任务?

0 个答案:

没有答案