現代のFortranでは、配列に引数として渡されたサブルーチンを持つのと同等のパフォーマンスを持つ関数から配列を返すことは可能ですか?Fortran 2008:関数の戻り値はどのように返されますか?
簡単な例ここで
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())
のような表現での使用は不可能です。
コンパイラの実装では、ヒープ上のすべての配列を割り当てることを選択したが、戻り値は2つのバージョン間の同等の性能が得られ、C
の根底にあるポインタを変更するだけで割り当てることができる場合。*
のようなものです一般的なコンパイラで行われた最適化、あるいはパフォーマンス上のオーバーヘッドなしに関数セマンティクスを得るための他の方法がありますか?
*割り当て可能な配列では明らかですが、これはコンパイラのサポートの問題になります。インテルFortranは、デフォルトでは、異なるサイズの配列の割り当て時には(再)配列を割り当てませんが、ALLOCATE(C, SOURCE=FUNC())
ステートメントを使用すると同じ効果が得られます。一方、Gfortranは割り当て時に自動割り当てを行いますが、形状がSOURCE
引数から派生し、修正がまだバイナリリリースに含まれていないALLOCATE
ステートメントを防ぐバグがあります。
万が一、fortranに「移譲」のセマンティクスを確立しようとしているのを知っていますか?あなたがデフォルトでそうすることに対して良い点を作ったのに対し、それは関数/戻り値に対する明示的な属性として実装できるもののようです。 – kdb
私はこのことについて聞いたことはありませんでしたが、2008年以来のメンバーです。サブルーチンコールであなたが望むものを達成できるので、それは私にとっては不必要な複雑さのようです。 –