2011-07-07 22 views
11

Fortranで可変サイズの配列を作成する方法はありますかのスタック? Allocate()はヒープ上に配列を配置するため、私にとっては機能しません。これは並列化の問題につながる可能性があります(私の他の質問: OpenMP: poor performance of heap arrays (stack arrays work fine)を参照してください)。もちろん、いくつかのスマートなメモリ管理はその問題を回避する方法を提供しますが、Fortranのメモリ管理は愚かなものです。Allocate()を使用しないFortranの可変サイズ配列

基本的に、私はCで、次のFortranの同等を探しています:

scanf("%d", N); 
int myarray[N]; 

再反復する:これは、コンパイル時に、配列のサイズを決定したので、私は

Integer, PARAMETER :: N=100 
Integer, Dimension(N) :: myarray 

を望んでいません時間。どちらも必要ありません

Integer, Dimension(:), Allocatable :: myarray 
read(*,*) N 
Allocate(myarray(1:N)) 

ヒープ上に配列が配置されるためです。

非常に感謝します。私は最近、上記の問題の問題に遭遇するまで、割り当て可能な配列に非常に満足していました。この質問に否定的な答えがある場合、私は非常にソースへのリンクを感謝します。

編集:M.S.B.の回答へのコメントを参照してください。これを行うエレガントな方法は、Fortran 2008でのみ可能になりました。これはblock構造で行われます。

答えて

11

Fortranは、実行時に次元がわかっている限り、サブルーチンへの入力時に宣言のみを自動的に作成できます。宣言された次元はパラメータ属性として宣言する必要はありません。 、

subroutine MySub (N) 

integer, intent (in) :: N 
real, dimension (N) :: array 

が有効です。だから、メインプログラム、またはいくつかのサブルーチンであなたのサイズ "N"を決めてから、別のサブルーチンを呼び出して続けるのはどうですか?おそらく、このアプローチでは、配列はスタック上にあります。 @eriktousが書いたように、Fortran言語標準ではこの動作が指定されていません。いくつかのコンパイラは、ローカル配列を特定のサイズを超えてヒープに切り替えます。いくつかのコンパイラは、この動作を制御するためのオプションを提供しています。ヒープ上に大きな配列を配置することは、おそらく再帰型またはOpenMPでオーバーライドされます。

allocatableとして宣言されているサブルーチンの仮引数を使用せずに、割り当て可能な配列を実際の引数としてサブルーチンに渡すこともできます。元の配列がまだヒープ上にある可能性があるため、これはあなたの懸念に役立ちません。

+1

ありがとう、M.S.B.! Cの 'int array [N]'と比較すると重くて、それはトリックです。 – drlemon

+0

Fortran 2008のブロック構造を使用して、コードの真ん中の宣言であるCに近いものを実行できます。例えば、p。 ftp://ftp.nag.co.uk/sc22wg5/N1701-N1750/N1729.pdfの12。どのコンパイラがこれをサポートしているのか、OpenMPでサポートしているのか分かりません。 –

+3

私のコードにはこの構造がありますが、デフォルトではgfortranはまだ配列をヒープに配置していますが、今はタイトなループの途中でmallocを使用しています。オプション "-fstack-arrays"が必要なようです。 – DaveP

5

Fortran標準にはスタックとヒープの概念がないため、これは実装(つまりコンパイラ)に依存します。例: gfortran、それはオプションがあります

 
-frecursive 
    Allow indirect recursion by forcing all local arrays to be allocated on the stack. 

他のコンパイラにも同様のオプションがあります。おそらくこれはあなたが望むことをするでしょう。

+0

ありがとう、それは興味深い考えです!しかし、これが適用される 'ローカル'配列は、配列サイズがインテント(in)引数として渡される関数で作成された配列です。私のテストでは、-frecursiveはAllocate()の結果に影響を与えませんでしたが、この面白い回避策に影響しました: 'subroutine doit(n);整数、インテント(in):: n;整数、次元(1:n):: myarray; !そうです。最後のサブルーチン... read(*、*)n; call doit(n) ' この場合、myarrayは-frecursiveの有無にかかわらずスタックに乗っているようです。少し変態しますが、トリックはします。私はx86_64でgcc 4.4.3を使用しています。 – drlemon

+0

@drlemon:そうです、私はこの特定のオプションがあなたが必要とするものを正確に行なわないことを恐れました。 GCC 4.4.3は古くからあり、特にFortranの観点からは古くなっています。 gfortranの開発はかなり活発になってきました。可能であれば、新しいバージョンが同じ問題を抱えている場合に試すことができます。また、もし私があなただったら、gfortranメーリングリストであなたの質問をします。これは実装の詳細に関係するため、開発者は可能なものと不可能なものを最もよく知っています。 – eriktous

関連する問題