fortran错误地调用了一个子例程

fortran错误地调用了一个子例程,fortran,profiling,linear-algebra,fortran90,Fortran,Profiling,Linear Algebra,Fortran90,我有一些Fortran 90代码,我一直在使用这些代码进行有限元计算。最近,我一直在努力改进它解决块线性系统的方法。之前,我有一个子例程amux用于稀疏矩阵向量乘法,另一个子例程cg使用amux实现共轭梯度法。我编写了一个新的矩阵向量子程序block\u amux,同样,我还编写了一个新的解算器block\u cg。当然,新方法应该运行得更快,但它的运行速度却慢了10倍 为了追踪问题,我使用了探查器gprof来查看发生了什么。我发现92.5%的代码用于运行cg子例程——尽管我从未调用过它,并且完

我有一些Fortran 90代码,我一直在使用这些代码进行有限元计算。最近,我一直在努力改进它解决块线性系统的方法。之前,我有一个子例程
amux
用于稀疏矩阵向量乘法,另一个子例程
cg
使用
amux
实现共轭梯度法。我编写了一个新的矩阵向量子程序
block\u amux
,同样,我还编写了一个新的解算器
block\u cg
。当然,新方法应该运行得更快,但它的运行速度却慢了10倍

为了追踪问题,我使用了探查器gprof来查看发生了什么。我发现92.5%的代码用于运行
cg
子例程——尽管我从未调用过它,并且完全依赖于block\u amux和block\u cg。为了使水更加浑浊,我在实际的
cg
例行程序中加入了一个打印语句,说“你好,世界”;它从未被印刷过。最后,我注意到gprof没有列出amux子例程的用法,即使对cg的真正调用会执行数百次普通矩阵乘法

我很困惑到底是什么在做这件事。有什么想法吗?如果有帮助的话,我可以附加gprof输出

更新:我做了以下更改,以某种方式产生了相同的结果:

  • 更改子程序的名称,例如
    cg
    变为
    conjugate\u gradient
    。然后Gprof报告说我在新的共轭梯度例程中浪费时间
  • 将我实际使用的子程序移到主程序的“contains”语句下,而不是它们原来所在的模块
    linalg_mod
    ,然后停止使用包含CG例程的模块。相反,该程序将时间浪费在所谓的“frame_dummy”中。这看起来很像,但我不能
  • 将我使用的子程序从包含CG例程的
    linalg\u mod
    移动到不包含CG例程的新模块
    linalg\u mod\u decoy
    。gprof没有在CG算法中浪费时间,而是说该程序调用了一个子程序,我用它来生成线性系统的右侧~3000次,而不是一次
  • 在另一台电脑上试试。没有区别
  • 引用问题作者的话:

    OpenMP是罪魁祸首。我认为,如果我将线程数设置为1,我将得到与在没有OMP的情况下分析相同的结果。当我停止使用OpenMP编译时,它的性能仍然很差,但正确地报告了所有工作的完成位置


    如果将“cg”子例程重命名为“dontcallthissubroutine”或其他名称,会发生什么情况?在这种情况下,我倾向于发现makefile中存在问题,并且我没有编译和运行我认为是的东西。这种想法发生在我身上。我把它重命名为“共轭梯度”,去掉了所有可执行文件、对象和模块文件,然后用同样的结果重建了所有文件。gprof报告说,在这个奇怪的子例程上花费了相同的时间,当然名称也改变了。不过,我将试着玩转如何编译所有内容。您可能已经知道这一点,但在重新编译之前,请确保清除旧的对象文件和创建的所有库。您的可执行文件的慢速版本是否有可能卡在缓存中?您是否尝试过从新的终端会话运行?或on/off开关?您使用哪种编译器?哪些优化标志有效?您的问题听起来很像内联和/或过程间优化之后发生的情况。每当编译插入指令的二进制文件时,应禁用内联和IPO。