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

时间:2013-10-16 15:56:39

标签: optimization fortran fortran90

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

问题陈述:

主代码有一个for / DO循环,其中存在子程序。子程序需要或不需要执行,具体取决于我从用户收到的标志。

明显的解决方案:

最简单的方法是使用IF循环来调用子程序。但是,如果每次执行循环时都必须检查标志,那么这很费时间。我正在进行分子动力学,循环执行的次数将是10 ^ 5的数量级。

问:有没有更好的方法来做到这一点,就像我对程序说,是否必须根据标志一劳永逸地调用子程序?我正在使用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

1 个答案:

答案 0 :(得分:3)

我不确定IF语句是否真的会减慢程序的速度,即使被调用(超过)100,000次。你可能只会通过重组代码来节省一两秒(尽管测试一下!)

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

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

其中第二个DO循环省略了子例程CALL


修改

另一种选择(实现起来可能更便宜)是预处理数据并在编译时键入标记。这可能会让用户在更改标志时不得不重新编译程序,但它会让您的工作更轻松。

无论如何,你有类似

的东西
    DO
       ...
#ifdef <flag>
       CALL <subroutine name>
#endif
    ENDDO