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

优化一维存储对称带状矩阵与通用二维矩阵的加法运算

对称带状矩阵与通用矩阵相加的Fortran性能优化方案

针对对称带状矩阵B(一维数组存储)与通用矩阵A相加的性能瓶颈问题,结合Fortran95和gfortran-8编译器,提供以下优化方案:

1. 减少循环内重复计算与内存访问次数

循环内重复计算索引、多次读取同一数组元素是性能损耗的核心原因之一。提前计算固定值、用临时变量缓存数组元素,能有效降低开销:

subroutine iter(n,ccc,matrix_A,array_B,const)
    implicit none
    integer,intent(in)::n,ccc
    complex*16,intent(inout)::matrix_A(n,n)
    complex*16,intent(in)::array_B(n*ccc), const
    integer::i,j,start_idx,offset
    complex*16::b_val

    do i=1,n
        start_idx = (i-1)*ccc + 1  ! 提前计算当前行的起始索引,避免重复计算
        ! 处理对角线元素(i,i)
        matrix_A(i,i) = matrix_A(i,i) + array_B(start_idx)*const
        ! 处理上三角及对称下三角元素
        do j=i+1,min(i+ccc-1,n)
            offset = j - i
            b_val = array_B(start_idx + offset)*const  ! 一次读取,多次使用
            matrix_A(i,j) = matrix_A(i,j) + b_val
            matrix_A(j,i) = matrix_A(j,i) + b_val
        end do
    end do
end subroutine iter

2. 开启编译器最高级优化选项

gfortran-8的优化选项能大幅提升代码性能,尤其针对循环和SIMD指令的利用,推荐编译时添加:

gfortran-8 -O3 -march=native -ffast-math -funroll-loops your_code.f90
  • -O3:启用全级别优化,包括循环展开、函数内联等
  • -march=native:针对当前CPU架构生成最优指令,充分利用AVX/SSE等SIMD扩展
  • -ffast-math:允许数学运算的近似简化,对复数运算性能提升显著(需确保精度符合需求)
  • -funroll-loops:强制展开内层小循环(本场景内层循环最多ccc-1次,非常适合)

3. 重构循环结构消除分支判断

原代码中的min(i+ccc-1,n)会引入条件分支,阻碍编译器向量化。将循环拆分为无边界判断的中间段和边界段,减少分支干扰:

subroutine iter(n,ccc,matrix_A,array_B,const)
    implicit none
    integer,intent(in)::n,ccc
    complex*16,intent(inout)::matrix_A(n,n)
    complex*16,intent(in)::array_B(n*ccc), const
    integer::i,j,mid_start,mid_end,start_idx,offset
    complex*16::b_val

    mid_start = ccc
    mid_end = n - ccc + 1

    ! 单独处理对角线元素
    do i=1,n
        matrix_A(i,i) = matrix_A(i,i) + array_B((i-1)*ccc +1)*const
    end do

    ! 处理前ccc-1行(存在上边界)
    do i=1,ccc-1
        do j=i+1,min(i+ccc-1,n)
            offset = j - i
            b_val = array_B((i-1)*ccc +1 + offset)*const
            matrix_A(i,j) = matrix_A(i,j) + b_val
            matrix_A(j,i) = matrix_A(j,i) + b_val
        end do
    end do

    ! 处理中间行(无边界判断,适合向量化)
    do i=mid_start,mid_end
        start_idx = (i-1)*ccc +1
        do j=i+1,i+ccc-1
            offset = j - i
            b_val = array_B(start_idx + offset)*const
            matrix_A(i,j) = matrix_A(i,j) + b_val
            matrix_A(j,i) = matrix_A(j,i) + b_val
        end do
    end do

    ! 处理后ccc-1行(存在下边界)
    do i=mid_end+1,n
        do j=i+1,n
            offset = j - i
            b_val = array_B((i-1)*ccc +1 + offset)*const
            matrix_A(i,j) = matrix_A(i,j) + b_val
            matrix_A(j,i) = matrix_A(j,i) + b_val
        end do
    end do
end subroutine iter

4. 按带状偏移量重构循环

将循环按带状的偏移量k(从1到ccc-1)拆分,让内存访问模式更连续,便于编译器优化:

subroutine iter(n,ccc,matrix_A,array_B,const)
    implicit none
    integer,intent(in)::n,ccc
    complex*16,intent(inout)::matrix_A(n,n)
    complex*16,intent(in)::array_B(n*ccc), const
    integer::i,k,idx_b
    complex*16::b_val

    ! 处理对角线(k=0)
    do i=1,n
        matrix_A(i,i) = matrix_A(i,i) + array_B((i-1)*ccc +1)*const
    end do

    ! 处理每个偏移量k对应的带状元素
    do k=1,ccc-1
        do i=1,n-k
            idx_b = (i-1)*ccc +1 + k
            b_val = array_B(idx_b)*const
            matrix_A(i,i+k) = matrix_A(i,i+k) + b_val
            matrix_A(i+k,i) = matrix_A(i+k,i) + b_val
        end do
    end do
end subroutine iter

这种方式下,matrix_A(i+k,i)访问的是列i的连续元素(Fortran列优先存储),内存访问更高效,编译器更容易实现向量化。

5. 显式启用SIMD向量化

如果编译器自动向量化效果不佳,可通过!$OMP SIMD指令强制对循环进行向量化优化(需确保编译时开启OpenMP支持:-fopenmp):

! 处理中间行时添加SIMD指令
do i=mid_start,mid_end
    start_idx = (i-1)*ccc +1
    !$OMP SIMD
    do j=i+1,i+ccc-1
        offset = j - i
        b_val = array_B(start_idx + offset)*const
        matrix_A(i,j) = matrix_A(i,j) + b_val
        matrix_A(j,i) = matrix_A(j,i) + b_val
    end do
end do

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:07:44