【问题标题】:Fortran optimization using Blas or not是否使用 Blas 进行 Fortran 优化
【发布时间】:2015-10-01 13:19:35
【问题描述】:

我有以下 Fortran 代码

DO ir = 1, N
     cfac = exp( ci*B ) / dble( degen(ir) )
     C(:,:) = C(:,:) + cfac*D(:,:, ir )
ENDDO

这个循环在 gcc -02 下需要 14.00 秒。

我想优化它。我试过 BLAS 进行矩阵向量乘法的例程:

DO ir = 1, N
   cfac(ir) = exp( ci*B ) / dble( degen(ir) )
ENDDO

DO j = 1, M
  CALL zgemv ('n', M, N, cone, D(j,:,:), M,cfac(:),1,czero, C(j,:), 1 )
ENDDO

事实证明,我得到了相同的结果,但在 ... 17.67 秒内。

为什么会变慢?如何改进代码(不更改编译器选项)?

谢谢你,

塞缪尔

【问题讨论】:

  • N 和 M 有多大?很可能那些 BLAS 例程根本无法帮助您,而您只是增加了开销。您尝试了哪种 BLAS 实现?编译器很擅长自己优化循环,我不在任何地方使用 GEMV。
  • 当您调用 zgemv 时,您也可能会复制输入/复制输出,因为您要在 C 和 D 中访问的元素在内存中不连续。特别是 D 的副本可能会扼杀你的表现。哦,这些是 BLAS 例程 - 这个问题与 ScaLAPACK 无关,而 ScaLAPACK 与 BLAS 非常不同。
  • 谢谢伊恩!我已将标题更改为 Blas。您认为可以通过修改代码(使用或不使用 Blas)来提高性能吗?通常 N 很大,而 M 不大。我为这两个循环计时。第一个是 4 秒,第二个是 13.67 秒,结果是 17.67 秒。
  • 我不这么认为。但是您仍然没有回复 N 和 M 的值是什么。如果您使用 gfortran,查看-fdump-tree-optimized 的输出会很有用。此外,请尝试-fopt-info 以了解编译器进行了哪些优化(例如矢量化)。您可能想尝试 -O2 以不同的方式展开一些循环,它可能会有所帮助,但也会造成伤害。总的来说,我还是很怀疑的,如果编译器已经将它向量化了,那么改进的空间就不大了。
  • 另外,不鼓励使用C(:,:),它可能会混淆优化器,请参阅software.intel.com/en-us/blogs/2008/03/31/…

标签: optimization fortran blas


【解决方案1】:

改进方法如下

DO ir = 1, N
     cfac = exp( ci*B ) / dble( degen(ir) )
     CALL zaxpy(M**2,cfac, D(1,1, ir ),1, C (1,1),1)
ENDDO

这样我大概从 15 秒到 13 秒。

【讨论】:

    猜你喜欢
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多