Optimization 优化从循环调用子例程的次数

Optimization 优化从循环调用子例程的次数,optimization,fortran,fortran90,Optimization,Fortran,Fortran90,关于优化程序的一个小问题。问题陈述如下 问题陈述: 主代码有一个for/DO循环,其中有一个子例程。子例程是否需要执行取决于我从用户收到的标志 显而易见的解决方案: 最简单的方法是使用IF循环调用子例程。但是,如果每次执行循环时都必须检查标志,那么这将非常耗时。我在做分子动力学,循环的次数是10^5 Qn:有没有更好的方法来实现这一点,就像我对程序说的,是否必须根据标志一次性调用子例程?我正在用Fortran 90编写代码。因此,如果可以这样说,那将是有益的 PROGRAM MAIN I

关于优化程序的一个小问题。问题陈述如下

问题陈述:

主代码有一个for/DO循环,其中有一个子例程。子例程是否需要执行取决于我从用户收到的标志

显而易见的解决方案:

最简单的方法是使用IF循环调用子例程。但是,如果每次执行循环时都必须检查标志,那么这将非常耗时。我在做分子动力学,循环的次数是10^5

Qn:有没有更好的方法来实现这一点,就像我对程序说的,是否必须根据标志一次性调用子例程?我正在用Fortran 90编写代码。因此,如果可以这样说,那将是有益的

PROGRAM MAIN
    IMPLICIT NONE
    "ALL ARRAY INITIALIZATIONS
     CALL DENSITY() ! I do a field based approach. So this is for grid formulation
    DO i = 1, neq ! neq = number of eqbm cycles
         CALL MC_CYC() ! Monte carlo steps
         CALL DENSITY() ! Recalculate density  
    END DO
    DO i = 1,nprod ! production cycle
       DO j = 1, niter ! for averages of ensembles
          CALL MC_CYC()
          CALL DENSITY()
       END DO
        !do average here
        IF(<flag is present>) ! This is where I needed to check flag. Because otherwise the flag will be checked everytime.
           CALL RDF()
        END IF
     END DO
  END PROGRAM MAIN
主程序
隐式无
“所有数组初始化
调用DENSITY()!我使用基于字段的方法。所以这是网格公式
i=1,neq!neq=eqbm循环数
调用MC_CYC()!蒙特卡罗步骤
调用密度()!重新计算密度
结束
i=1,nprod!生产周期
对于合奏的平均值,j=1,niter
调用MC_CYC()
呼叫密度()
结束
!你在这里平均吗
IF()!这是我需要检查标志的地方。否则每次都会检查标志。
调用RDF()
如果结束
结束
主程序结束

我不确定
IF
语句是否真的会降低程序的速度,即使调用了(超过)100000次。通过重新构造代码,您可能只会节省一两秒钟的时间(尽管要测试!)

无论如何,如果在程序开始时收到该标志,那么您就可以将代码编写为

IF(<flag is present>) THEN
   DO
      ...
      CALL <subroutine name>
      ...
   ENDDO
ELSE
   DO
      ...
   ENDDO
ENDIF

哇,Fortran 90…你在哪里使用它?@AdamStelmaszczyk“在哪里?”“在这个意义上?我用它来进行分子动力学编码。如果你在做MD,我想在你的do循环中会有很多其他的操作。那么,
如果
就根本不重要了。不要试图优化你的单个
ıf
语句,试着优化代码的那一部分,这会占用你的时间。但是,首先,分析你的代码,以便知道它在哪里花费了大部分的执行时间。有一件小事我之前没有告诉你。无论标志是否存在,都需要执行DO循环,因为存在其他子例程(无论标志如何,这些子例程都是必需的)。有一些用于后处理的子程序,只有在标志为true时才需要调用这些子程序。如果我这样做,整个循环(它本身很大,需要写两次)@Vaidyanathan:我在我的答案中添加了第二个选项,可能更适合你。这看起来不错。只是个问题。#ifdef是否只执行一次?我不太熟悉#ifdef。
#ifdef…#endif
是预处理器指令。它们在编译时应用一次&以后不再应用。我想这是一个很好的方法。
    DO
       ...
#ifdef <flag>
       CALL <subroutine name>
#endif
    ENDDO