2013-10-16 35 views
1

優化程序的一個小問題。該問題如下優化子程序從循環中調用的次數

問題陳述指出:

主碼具有對/ 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 
+1

哇,Fortran 90的......你在哪裏使用它? –

+0

@AdamStelmaszczyk「哪裏」在某種意義上?我正在使用它進行分子動力學編碼。 – Vaidyanathan

+1

如果你在做MD,你會在do-loop中做很多其他的操作,我想。那麼'if'應該不是真的很重要。不要試圖優化你的單個'ıf'語句,嘗試優化代碼的這一部分,這真的會縮短你的時間。但是,首先,分析您的代碼,以瞭解它在哪裏花費大部分執行時間。 –

回答

3

我不知道,一個IF聲明是真的要程序變慢,即使所謂的(超過)10萬次。你可能只會通過重組代碼來保存一兩秒鐘(測試這個雖然!)

無論如何,如果在程序開始時收到標誌,那麼你就可以寫你的代碼爲

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

其中第二個DO迴路省略子程序CALL


EDIT

作爲另一替代方案(這可能是更便宜的實現)是預先處理的數據,並具有在編譯時鍵入的標誌。這可能會讓用戶有點惱火,在更改標誌時必須重新編譯程序,但它會讓您的工作更輕鬆。

無論如何,你必須像

DO 
     ... 
#ifdef <flag> 
     CALL <subroutine name> 
#endif 
    ENDDO 
+0

這確實是一個好主意(這並沒有打動我!)。我之前沒有講過一件小事。無論是否存在標誌,都需要執行DO循環,因爲存在其他子程序(無論標誌是否爲必需)。有些後處理子程序只有在標誌爲真時才需要調用。如果我這樣做,整個循環(本身很大,需要寫兩遍) – Vaidyanathan

+0

@Vaidyanathan:我在我的答案中增加了第二個選項,可能會更適合你。 –

+0

這看起來不錯。就一個問題。 #ifdef是否只執行一次?我對#ifdef並不熟悉。 – Vaidyanathan