簡體   English   中英

Fortran 2008:如何返回函數返回值?

[英]Fortran 2008: How are function return values returned?

在現代Fortran中是否有可能從一個函數返回一個數組,其性能等同於子程序填充一個作為參數傳遞的數組?

考慮例如作為簡單的例子

PROGRAM PRETURN 

  INTEGER :: C(5)
  C = FUNC()
  WRITE(*,*) C
  CALL SUB(C)
  WRITE(*,*) C

CONTAINS 

  FUNCTION FUNC() RESULT(X)
    INTEGER :: X(5)
    X = [1,2,3,4,5]
  END FUNCTION FUNC

  SUBROUTINE SUB(X)
    INTEGER :: X(5)
    X = [1,2,3,4,5]
  END SUBROUTINE SUB

END PROGRAM PRETURN

這里, C = FUNC()行將從函數返回值中復制值,然后從堆棧中丟棄返回的數組。 子程序版本CALL SUB(C)將直接填充C ,避免額外的應對步驟和與臨時數組相關的內存使用 - 但不能在SUM(FUNC())這樣的SUM(FUNC())使用。

但是,如果編譯器實現選擇在堆上分配所有數組,則只需通過更改C的基礎指針即可分配返回值,從而在兩個版本之間獲得相同的性能。*

這些優化是由通用編譯器完成的,還是有其他方法來獲得函數語義而沒有性能開銷?


*使用可分配數組會更加明顯,但這會遇到編譯器支持問題。 默認情況下,英特爾fortran在分配不同大小的數組時不會(重新)分配數組,但通過使用ALLOCATE(C, SOURCE=FUNC())語句可以產生相同的效果。 Gfortran同時執行賦值時的自動分配,但是有一個錯誤可以阻止ALLOCATE語句,其中形狀是從SOURCE參數派生的,而修復程序尚未包含在二進制版本中。

Fortran標准沒有提到實現該語言中幾乎所有內容的實際機制。 該語言的語義是在賦值開始之前完全評估函數結果。 如果一個人將目標作為輸出傳遞,那么如果函數由於某種原因沒有完成,那么變量可能會被部分修改。 編譯器可能能夠進行足夠的重疊分析以進行一些優化。 我很確定英特爾Fortran沒有這樣做 - 語義限制很重要。

你的例子是一個玩具程序 - 更有趣的問題是,如果有生產應用程序,這樣的優化是適用和值得的。

我將評論英特爾Fortran將更改其分配給可分配陣列的默認行為,以便從版本17開始,將按照標准的規定進行自動重新分配。

我有時也有相同的。 當我停下來思考片刻時,我意識到功能是如此的好,而且當它涉及到fortran時子程序也很好。

想象一下能力就在那里,我們有以下功能:

function doThings(param) results(thing)
    integer :: thing
    integer, intent(in out) :: param
    ! Local variables
    integer :: genialUpdatedValue, onOfThePreviousResult
    ! some other declarations
    ! serious computation to do things
    ! and compute genialUpdatedValue and onOfThePreviousResult
    param = genialUpdatedValue
    thing = onOfThePreviousResult
end function doThings

我們有以下電話:

! some variables first
integer, parameter :: N_THINGS = 50 ! just love 50
integer :: myThing, myParam
integer, dimension(N_THINGS) :: moreThings
!
! Reading initial param from somewhere
! myParam now has a value
!
myThing = doThings(myParam)

那肯定沒關系,下面怎么樣

!
! Reading initial param from somewhere
! myParam now has a value
!
moreThing = doThings(myParam)

結果會是什么? 好吧

integer :: i
do i = 1, N_THINGS
    moreThings(i) = doThings(myParam)
end do

或者是這個

integer :: i, thing
thing = doThings(myParam)
do i = 1, N_THINGS
    moreThings(i) = thing
end do

請記住, myParam會被函數更改。 可以說這是一個簡單的情況,但是圖像結果不是整數,而是具有大數組成員的用戶定義類型。

如果你考慮一下,你一定會發現一些像這樣的問題。 當然,可以在這里添加更多限制以允許該功能,並且最終,當我們有足夠的需求時,它將以必要的限制來實現。 我希望有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM