You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共轭梯度与带状矩阵向量乘法组合模块误差原因排查求助

问题排查:共轭梯度法与带状矩阵-向量乘法组合后的误差问题

我实现了两个Fortran模块:

  • 共轭梯度法(conjugate gradient method)
  • 带状矩阵-向量乘法(band matrix-vector multiplication)

两个模块单独运行时,仅因加法非结合性存在1e-14至1e-15级别的机器误差。但组合运行后,自定义matVecMult模块与常规矩阵向量乘法的结果差异显著,无法定位误差原因,恳请协助排查。

相关数据与模块代码

核心数据

  • 稠密带状矩阵:dnsa
  • 稀疏矩阵:a
  • 非零对角线索引向量:
cols = [1 2 3 4 5 6 9]

CG求解器模块

module LinSolver
    use denseTimesVec
    implicit none
    contains
    subroutine cg(a,dnsa,n,b,cols,x)
        implicit none
        integer*8, intent (in) :: n
        real*8, intent (in) :: a(:,:)
        real*8, intent (in) :: dnsa(:,:)
        real*8, intent (inout):: b(:)
        real*8, intent (out) :: x(:)
        integer*8, intent (in) :: cols(:)


        ! local variables
        integer :: i, j, k
        real*8, dimension(n) :: r, p, Ap, ApDNS
        real*8, parameter :: eps = 1.e-6
        real*8 :: rsold, rsnew, alpha, pAp

        call matVecMult(n,dnsa,x,cols,ApDNS)
        do i = 1,n
            Ap(i) = 0
            do j = 1,n
                Ap(i) = Ap(i) + a(i,j) * x(j)
            enddo
        enddo
        print*,cols

        r = b - Ap
        p = r

        rsold = 0;
        do j = 1,n
            rsold = rsold + r(j)*r(j);
        enddo
        
        
        do i=1,n
            call matVecMult(n,dnsa,p,cols,ApDNS)
            do k = 1,n
                Ap(k) = 0;
                do j = 1,n
                    Ap(k) = Ap(k) + A(k,j) * p(j);
                enddo
            enddo
            
            pAp = 0;
            do j = 1,n
                pAp = pAp + Ap(j) * p(j);
            enddo
            alpha = rsold / pAp;
            x = x + alpha * p;
            r = r - alpha * Ap;
            rsnew = 0;
            do j = 1,n
                rsnew = rsnew + r(j)*r(j);
            enddo
            if (sqrt(rsnew)<eps) exit
            p = r + (rsnew / rsold) * p
            rsold = rsnew
        enddo
    end subroutine cg
end module LinSolver

带状矩阵-向量乘法模块

module denseTimesVec
    
    implicit none
    contains
    subroutine matVecMult(n,a,x,cols,b)
    
    implicit none        
    integer*8, intent (in) :: n
    real*8, intent (out) :: b(:)
    real*8, intent (in):: a(:,:), x(:)
    integer*8, intent (in) :: cols(:)
    integer*8   ::  i, j, width
    real*8, dimension (:), allocatable :: xTimesUpper, xTimesLower
    
    allocate ( xTimesUpper(n), xTimesLower(n)) 
    
    
    do j = 1,size(cols)
        width = cols(j)-1;
        do i = 1,n-width
            if (width == 0) then
                b(i) = b(i)+a(i,1)*x(i);
            else
                xTimesUpper = x(1+width:n);
                xTimesLower = x(1:n-width);
                
                ! multiplying upper/lower part
                b(i) = b(i) + a(i,j) * xTimesUpper(i); ! OK if compared to triuA*x-b
                b(i+width) = b(i+width) + a(i,j)*xTimesLower(i);
            endif
        enddo
    enddo
    
    end subroutine matVecMult
    
    end module denseTimesVec

内容的提问来源于stack exchange,提问作者2Napasa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 04:18:15