2016-06-29 42 views
0

使用靜態變量在子例程中存儲狀態是否是一種好的做法?我心裏有類似以下內容:「一些東西」使用靜態變量在子例程中存儲狀態是否是一種好的做法?

subroutine somesub() 
logical, save :: first_call = .true. 


if (first_call) then 
! do some stuff 

first_call = .false. 
end if 

! ... perform standard work 

end subroutine somesub 

例子包括:

  1. 分配工作陣列。這可能是最好的自動數組。
  2. 初始化需要某種運行時評估的物理/數學常量。一個很好的例子是pi = datan(1.0)*4d0
  3. 從名單或文本文件中讀取一些參數和物理名稱。

根據this question,在使用多線程的情況下,使用靜態變量來存儲這樣的狀態將被忽略。這是一個典型的fortran物理模擬代碼中的openmp或mpi問題嗎?

對於特定於子程序的物理常數和用戶可修改參數,您還推薦了哪些替代方法?

+3

這似乎是基於對我相當的意見。我建議使用模塊或派生類型並將數據存儲在那裏。並使用單獨的初始化或配置過程。 –

+0

借調。正如你暗示的那樣,在與OpenMP並行時,這種風格會成爲一種正確的皇家痛苦,它只是要求競爭條件;有一個單獨的初始化程序,並將其粘貼在一個模塊中。哦,datan是Fortran 66風格的,atan很好,現在你可以在參數聲明中使用這個表達式。 –

+0

你是否嚴格談論固定參數?使用「狀態」這個詞讓我覺得sub可能會改變它的值(在初始調用後) – agentp

回答

1

這太長太具啓發性,無法成爲評論,所以我把它作爲答案。它闡述了VladimirF的評論。

如果一個子程序足夠具有自己的一組參數,而該程序的任何其他部分都無法訪問該參數,那麼請爲該子程序創建一個模塊。將子程序的參數添加爲模塊的私有實體,添加子程序本身(僅限標準工作)並添加初始化子程序並最終生成子程序。

確保您的程序調用初始化子例程並最終完成子例程。對我而言,這是一個優雅地適用於將來可能會出現的一般情況的最佳做法。例如,如果需要保存子程序的狀態或釋放一些系統資源,則最終確定是最好的。

這將在MPI環境中很好地工作,其中每個實例可能有自己的一組子參數。只要您知道何時調用初始化,它對於openmp也會很方便。

您的模塊可能是這樣的:

module some_mod 
implicit none 
    private 
    ! declare all the stuff that are private to your module here 
    public somesub, init_somesub, finalize_somesub 
contains 

    subroutine somesub() 
     ! 
     ! perform only the standard work, nothing else 
     ! 
    end subroutine somesub 

    subroutine init_somesub() 
     ! 
     ! do only the initialization here 
     ! 
    end subroutine init_somesub 

    subroutine finalize_somesub() 
     ! 
     ! do some stuff here to finalize if necessary 
     ! 
    end subroutine finalize_somesub 

end module some_mod 
+0

有沒有一種方法可以強制執行一個規則:「somesub」不能修改模塊範圍變量? – agentp

+0

如果你想隱藏'somesub'中的一些變量,只需將它們放在另一個'module'中作爲私有變量,或者不要在'module'中使用'module'來定義'somesub'。據我所知,所有模塊變量都可以被該模塊中定義的所有過程訪問。首先,這個'module'的目標是獲取'somesub'中保存的變量,並使它們成爲private''module'變量,只能通過'somesub'和初始化和finification過程訪問。 – innoSPG

+1

這似乎確實是最佳做法。這有點像使用模塊作爲C++中的單例類。 – nbren12

相關問題